------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
Collection: 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。
一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。
此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。
数组和集合类的区别:
数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。
数组中可以存储基本数据类型,集合只能储对象。
集合类的特点:
集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
Collection接口:
List接口:可存放重复元素,元素存取是有序的。
Set:不可以存放重复元素,元素存取是无序的。
add方法的参数类型是Object,以便于接受任意类型对象。
集合中存储的都是对象的引用(地址)。
什么是迭代器:
其实就是集合的取出元素的方式。
迭代器的内部实现:
把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内部的元素。那么取出方式就被定义成了内部类。
而每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都有共性内容判断和取出。那么可以将共性抽取。
Collection:
List:元素是有序的,元素可以重复。因为该集合体系有索引。
ArrayList:底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步。
当元素超过10个,则自动延长,50%延长。
LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。
Vector:底层是数组数据结构。线程同步。被ArrayList替代了。因为效率低。当元素超出10个,100%延长。
List集合功能:
1、添加:
add(index,element);
addAll(index,Collection);
2、删除:
remove(index);
3、修改:
set(index,element);
4、查询:
get(index);
subList(from,to);
listIterator();
int indexOf(obj):获取指定元素的位置。
ListIterator listIterator();
List集合特有的迭代器。ListIterator是Iterator的子接口。
在迭代时,不可以通过集合对象的方法操作集合中的元素。
因为会发生ConcurrentModificationException异常。
所以,在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,
取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator。
该接口只能通过List集合的listIterator方法获取。
在迭代过程中,准备添加或者删除元素。
Iterator it = al.iterator();
while(it.hasNext())
{
Object obj = it.next();
if(obj.equals("java02"))
al.add("java008");
}
此时将抛出ConcurrentModificationException异常
枚举就是Vector的特殊取出方式。
public static void main(String[] args)
{
Vector v = new Vector();
v.add("java01");
v.add("java02");
v.add("java03");
v.add("java04");
Enumeration en = v.elements();
while(en.hasMoreElements())
{
System.out.println(en.nextElement());
}
}
LinkedList:
LinkedList的特有方法:
addFirst();
addLast();
getFirst();
getLast();获取元素,但不删除元素。如果集合中没有元素,则抛出异常。
removeFirst();
removeLast();获取元素,但是元素被删除,如果集合中没有元素,则抛出异常。
在JDK 1.6出现了替代方法:
offerFirst();
offerLast();
peekFirst();
peekLast();获取元素,但不删除元素。如果集合中没有元素,返回null。
pollFirst();
pollLast();获取元素,但是元素被删除,如果集合中没有元素,则返回null。
练习:使用LinkedList模拟一个堆栈或者队列数据结构。
class DuiLie
{
private LinkedList link;
DuiLie()
{
link = new LinkedList();
}
public void myAdd(Object obj)//添加元素进入队列
{
link.addFirst(obj);
}
public Object myGet()//拿出元素,并移除这个元素
{
return link.removeFirst();
}
public boolean isNull()//判断队列中是否有元素
{
return link.isEmpty();
}
}
class LinkedListTest
{
public static void main(String[] args)
{
DuiLie dl = new DuiLie();//初始化并添加元素
dl.myAdd("java01");
dl.myAdd("java02");
dl.myAdd("java03");
dl.myAdd("java04");
while(!dl.isNull())//如果队列不为空,则取出元素
{
System.out.println(dl.myGet());
}
}
}
练习:去除ArrayList集合中的重复元素。
class ArrayListTest
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
ArrayList al = new ArrayList();//初始化一个ArrayList对象
al.add("java01");//并添加元素
al.add("java02");
al.add("java01");
al.add("java02");
al.add("java01");
sop(al);//打印原集合
al = singleElement(al);
sop(al);//打印去掉重复元素的集合
}
public static ArrayList singleElement(ArrayList al)
{
//定义一个临时容器。
ArrayList newAl = new ArrayList();
Iterator it = al.iterator();//遍历原集合
while(it.hasNext())
{
Object obj = it.next();
if(!newAl.contains(obj))//如果新集合不包含这个元素则存入新集合
newAl.add(obj);
}
return newAl;
}
}
Set集合:
Set:元素是无序(存入和取出的顺序不一定一致),元素不可以重复。
HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
HashSet保证元素的唯一性:
1、是通过元素的两个方法,hashCode和equals来完成。
2、如果元素的HashCode值相同,才会判断equals是否为true。
3、如果元素的hashcode值不同,不会调用equals。
对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。
Set集合的功能和Collection是一致的。
练习:往hashSet集合中存入自定对象姓名和年龄相同为同一个人,重复元素。
class HashSetTest
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
HashSet hs = new HashSet();//定义一个HashSet
//向这个集合中添加自定义元素
hs.add(new Person("a1",11));
hs.add(new Person("a2",12));
hs.add(new Person("a3",13));
//遍历这个集合
Iterator it = hs.iterator();
//打印集合中的内容
while(it.hasNext())
{
Person p = (Person)it.next();
sop(p.getName()+"::"+p.getAge());
}
}
}
class Person
{
private String name;//人的属性
private int age;
Person(String name,int age)
{
this.name = name;
this.age = age;
}
//覆盖hashCode值和equals方法
public int hashCode()
{
System.out.println(this.name+"....hashCode");
return name.hashCode()+age*37;
}
//如果姓名和年龄相同就为同一个人
public boolean equals(Object obj)
{
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
System.out.println(this.name+"...equals.."+p.name);
return this.name.equals(p.name) && this.age == p.age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
TreeSet集合:
可以对Set集合中的元素进行排序。底层数据结构是二叉树。
保证元素唯一性的依据:compareTo方法return 0.
TreeSet排序的第一种方式:让元素自身具备比较性。
元素需要实现Comparable接口,覆盖compareTo方法。
也种方式也成为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式:
当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。在集合
初始化时,就有了比较方式。定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器排序为主。
练习:按字符串长度排序
class TreeSetTest
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet(new StrLenComparator());//创建一个TreeSet,并传入一个比较器
ts.add("abcd");//添加元素
ts.add("cc");
ts.add("cba");
ts.add("aaa");
ts.add("z");
ts.add("hahaha");
Iterator it = ts.iterator();//遍历打印这个集合,查看排序结果
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
class StrLenComparator implements Comparator
{
public int compare(Object o1,Object o2)//覆盖compare方法
{
String s1 = (String)o1;
String s2 = (String)o2;
int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));//字符串按长度从短到长排序
if(num==0)
return s1.compareTo(s2);
return num;
}
}
Map集合:
该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
1,添加:
put(K key, V value)
putAll(Map<? extends K,? extends V> m)
2,删除:
clear()
remove(Object key)
3,判断:
containsValue(Object value)
containsKey(Object key)
isEmpty()
4,获取:
get(Object key)
size()
values()
entrySet()
keySet()
Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。
HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。
TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。
map集合的两种取出方式:
1、Set<k> keySet:将map中所有的键存入到Set集合。因为set具备迭代器。
所有可以迭代方式取出所有的键,在根据get方法。获取每一个键对应的值。
Map集合的取出原理:将map集合转成set集合。在通过迭代器取出。
2、Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry
Entry其实就是Map中的一个static内部接口。
为什么要定义在内部:
因为只有有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。
而且该事物在直接访问Map集合中的元素。
interface Map
{
public static interface Entry
{
public abstract Object getKey();
public abstract Object getValue();
}
}
class HashMap implements Map
{
class Hahs implements Map.Entry
{
public Object getKey(){}
public Object getValue(){}
}
}
Map的取出方式:
class MapDemo2
{
public static void main(String[] args)
{
Map<String,String> map = new HashMap<String,String>();
map.put("02","zhangsan2");
map.put("03","zhangsan3");
map.put("01","zhangsan1");
map.put("04","zhangsan4");
//将Map集合中的映射关系取出。存入到Set集合中。
Set<Map.Entry<String,String>> entrySet = map.entrySet();
Iterator<Map.Entry<String,String>> it = entrySet.iterator();
while(it.hasNext())
{
Map.Entry<String,String> me = it.next();
String key = me.getKey();
String value = me.getValue();
System.out.println(key+":"+value);
}
/*
//先获取map集合的所有键的Set集合,keySet();
Set<String> keySet = map.keySet();
//有了Set集合。就可以获取其迭代器。
Iterator<String> it = keySet.iterator();
while(it.hasNext())
{
String key = it.next();
//有了键可以通过map集合的get方法获取其对应的值。
String value = map.get(key);
System.out.println("key:"+key+",value:"+value);
}
*/
}
}
Map练习:
每一个学生都有对应的归属地。学生Student,地址String。
学生属性:姓名,年龄。
注意:姓名和年龄相同的视为同一个学生。保证学生的唯一性。
class Student implements Comparable<Student>
{
//定义学生的属性
private String name;
private int age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
//学生实现了Comparable接口,覆盖compareTo方法
//按年龄排序,如果年龄相等,则比较姓名
public int compareTo(Student s)
{
int num = new Integer(this.age).compareTo(new Integer(s.age));
if(num==0)
return this.name.compareTo(s.name);
return num;
}
//重写hashCode()和equals方法
public int hashCode()
{
return name.hashCode()+age*34;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new ClassCastException("类型不匹配");
Student s = (Student)obj;
return this.name.equals(s.name) && this.age==s.age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public String toString()
{
return name+":"+age;
}
}
class MapTest
{
public static void main(String[] args)
{
//初始化HashMap,并加入元素
HashMap<Student,String> hm = new HashMap<Student,String>();
hm.put(new Student("lisi1",21),"beijing");
hm.put(new Student("lisi1",21),"tianjin");
hm.put(new Student("lisi2",22),"shanghai");
hm.put(new Student("lisi3",23),"nanjing");
hm.put(new Student("lisi4",24),"wuhan");
//第一种取出方式 keySet
Set<Student> keySet = hm.keySet();
Iterator<Student> it = keySet.iterator();
while(it.hasNext())
{
Student stu = it.next();
String addr = hm.get(stu);
System.out.println(stu+".."+addr);
}
//第二种取出方式 entrySet
Set<Map.Entry<Student,String>> entrySet = hm.entrySet();
Iterator<Map.Entry<Student,String>> iter = entrySet.iterator();
while(iter.hasNext())
{
Map.Entry<Student,String> me = iter.next();
Student stu = me.getKey();
String addr = me.getValue();
System.out.println(stu+"........."+addr);
}
}
}
练习:
"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。
希望打印结果:a(1)c(2).....
class MapTest3
{
public static void main(String[] args)
{
String s = charCount("ak+abAf1c,dCkaAbc-defa");
System.out.println(s);
}
public static String charCount(String str)
{
char[] chs = str.toCharArray();//把字符串变为一个字符数组
TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();//建立TreeSet
int count = 0;//初始化计数器
for(int x=0; x<chs.length; x++)
{
//判断是否为字母
if(!(chs[x]>='a' && chs[x]<='z' || chs[x]>='A' && chs[x]<='Z'))
continue;
//取出计数器的值
Integer value = tm.get(chs[x]);
//如果存在,则计数器+1保存
if(value!=null)
count = value;
count++;
tm.put(chs[x],count);//直接往集合中存储字符和数字,为什么可以,因为自动装箱。
count = 0;
}
StringBuilder sb = new StringBuilder();//按顺序将键值对保存进sb中
Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator();//遍历entry
while(it.hasNext())
{
Map.Entry<Character,Integer> me = it.next();
Character ch = me.getKey();
Integer value = me.getValue();
sb.append(ch+"("+value+")");
}
return sb.toString();
}
}
Collections集合工具类:
Collections:集合框架的工具类。里面定义的都是静态方法。
Collections和Collection的区别:
Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。
它有两个常用的子接口:
List:对元素都有定义索引。有序的。可以重复元素。
Set:不可以重复元素。无序。
Collections是集合框架中的一个工具类。该类中的方法都是静态的。
提供的方法中有可以对list集合进行排序,二分查找reverseOrder//reverseOrder(比较器)等方法。
通常常用的集合都是线程不安全的。因为要提高效率。
如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。
Arrays用于操作数组的工具类。
asList:将数组变为一个List集合;将数组变成集合,不可以使用集合的增删方法。因为数组的长度是固定的。
如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。
如果数组中的元素都是基本数据类型,会将该数组作为集合中的元素存在。
class ArraysDemo {
public static void main(String[] args) {
String[] arr = {"abc","cc","kkkk"};
List<String> list = Arrays.asList(arr);
//int[] nums = {2,4,5};
Integer[] nums = {2,4,5};
List<Integer> li = Arrays.asList(nums);
/*
如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素。
如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。
*/
sop(li);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
集合变数组:
Collection接口中的toArray()方法;
1、指定类型的数组长度小于了集合的size,那么该方法内部会创建一个 新的数组,长度为集合的长度。
当指定类型的数组长度大于了集合的长度,就不会新创建数组,而是使用传递进来的数组。所以创建
一个刚刚好的数组最优。
2、将集合变数组是为了限定对元素的操作。
转自 http://blog.sina.com.cn/s/blog_466c66400100hw0i.html--提升性能的同时为你节约10倍以上成本From: http://blog.sina.com.cn/iyangjian一, 引子二,总体结构图三,系统结构综述四,环境配置以及底层基础类库五, Memcache & Mysql 常用场景案例六,更多
1.__str__ 和 __repr__Python的内置函数 repr() 能够把对象用字符串的形式表达出来,方便我们辨认。这就是“字符串表示形式”。根据 Python 文档中定义 __str__:通过 str(object) 以及内置函数 format() 和 print() 调用以生成一个对象的“非正式”或格式良好的字符串表示。返回值必须是字符串对象。 __repr__:是由 repr() 内置函数调用,用来输出一个对象的“官方”字符串表示。返回值必须是字符串对象,此方法通..
在pongba的讨论组上看到一道Amazon的面试题:找出给定字符串里的最长回文。例子:输入XMADAMYX。则输出MADAM。这道题的流行解法是用后缀树(Suffix Tree)。这坨数据结构最酷的地方是用它能高效解决一大票复杂的字符串编程问题: 在文本T里查询T是否包含子串P(复杂度同流行的KMP相当)。文本T里找出最长重复子串。比如abcdabcefda里abc同da都重复出现,
1: 必要准备 1): jdk&jre 2): adt-bundle 3): android ndk r9 4): python2.7 5): cocos2d-x 3.0 alpha02: 依次安装或者解压3: 添加/扩充环境变量 1): Path: C:\Python27;E:\android-ndk-r9 2): NDK_RO...
Code:&lt;?php // This file is protected by copyright law &amp; provided under license. Copyright(C) 2005-2009 www.vidun.com, All rights reserved. $OOO0O0O00=__FILE__;$OOO000000=urldecode('%74%68...
1 如果知道发生异常的时间段,可以查看这个时间段的日志: sed -n '/Jun 8, 2017 6:22:50/,/Jun 8, 2017 6:22:51/p' catalina.out |cat 时间格式要与日志时间格式匹配,且都存在;2 如果知道多少行到多少行发生了日志: sed -n '起始行号,结束行号p' catalina.out |cat 3 按异常搜索,如果直接知道是什么异常最...
使用winsocket2 进行网络编程,非控件。
以前做过一个性能测试项目,基于nginx+Hbase+Hadoop,第一次接触开源的东西,遇到各种问题,印象深的是Hbase和Hadoop的监控,当时也搜索到可以用开源的监控工具或写代码通过JMX取JVM的信息。在摸索的过程中发现一种更简单方便的办法,不用监控工具和写大量代码,直接用loadrunner脚本(该办法可能不专业,但是能用,可以让项目尽快进行,仅供参考)。我们知道Hbas...
旷视的AlignedReID,很有意思。 The end-to-end learning with structure prior is more powerful than a “blind” end-to-end learning.reid难点: 目前triplet loss等用的比较多。Combining softmax loss with metric learning
LightOJ - 1248 Dice (III)题意给你一个n面的均匀的骰子,问期望摇多少次可以看到所有的面。做法首先我们设dp[i]为当前看到不同的i面,可以看到所有面的期望次数,很显然dp[n]=0之后我们可以根据概率得到转移方程dp[i]=(n−in∗(dp[i+1]+1))+in∗(dp[i]+1)dp[i]=(\frac{n-i}{n}*(dp[i+1]+1))+\frac...
Bayes for Beginners: Probability and Likelihood 好好看,非常有用。以前死活都不理解Probability和Likelihood的区别,为什么这两个东西的条件反一下就相等。定义:Probability是指在固定参数的情况下,事件的概率,必须是0-1,事件互斥且和为1. 我们常见的泊松分布、二项分布、正态分布的概率密度图描述的就是这个。L...
Linux里文件命名比较宽泛的,一般没什么限制。不过不能用,因为这个是重定向的意思。UNIX其实不会根据扩展名来区分文件,但一般有些其他软件,比如编译器啊会识别扩展名。比如.c和.cpp是C和C++代码的源文件.sh是shell程序的文件。当然还有好多,这里先列个大概的表吧.bin 一般是二进制的文件,有些可以执行的.sh 一般是shell脚本的文件,但如果你不加这个扩展名,照样可以执行这个she