Java集合
①Collection接口
图示
常用方法
-
add(Object obj);//增
addAll(Collection coll);//增加coll集合
size();//查看大小
isEmpty();//是否为空
clear();//清楚所以元素
contains(Object obj);//判断是否含有obj元素
containsAll(Collection coll);//判断是否包含coll整个集合
remove(Object obj);//删
removeAll(Collection coll);//删去该集合中的coll集合
retainsAll(Collection coll);//求两个集合的交集
equals(Object obj);//比较,有些需重写equals方法
toArray();//变成数组
iterator();//迭代器
Collection集合与数组之间的转换
-
//集合 ---> 数组
Collection coll = new ArrayList();
Object[] arr = coll.toArray();
//数组 ---> 集合
List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"});//√
List arr1 = Arrays.asList(new Integer[]{123, 456});//√
List arr2 = Arryas.asList(123,456);//√
List arr3 = Arrays.asList(new int[]{123, 456}); //×,会被当做一个元素
②Iterator接口
实现对Collection的遍历
1、使用迭代器
-
Collection coll = new ArrayList();
Iterator ite = coll.iterator();//每次调用iterator()方法就会生成一个新的迭代器对象,相当于个指针吧,指向集合首元素前一位
while(ite.hasNext()){//判断是否有下个元素
System.out.println(ite.next());//指针下移,返回该位置上的元素
}
//Iterator中含有自己的remove()方法,与Collcetion中不同
//可以在遍历的时候删除元素
while(ite.hasNext()){
Object obj = ite.next();
if(XXX.equals(obj)){
ite.remove();
}
}
//每次遍历完,如果想重写遍历,就要重写迭代器,因为遍历完,原先迭代器,指向最后一位,不会重新指向首元素的前一位
Iterator ite = coll.iterator();
2、使用增强for循环
-
Collection coll = new ArrayList();
for(Object i : coll){
System.out.println(i);
}
③子接口一:List接口(存储序的、可重复的数据)
三个实现类
-
|----ArrayList:作为List接口的主要实现类;线程不安全的,效率高;底层使用Object[] elementData存储
-
|----LinkedList:对于频繁的插入、删除操作,使用此类效率比ArrayList高;底层使用双向链表存储
-
|----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[] elementData存储
常用方法
-
List list = new ArrayList();
list.add(Object a);//增
list.add(int index,Object a);//在index处插入元素
list.addAll(int index,Collection coll);//在index插入一个集合
list.get(int index);//获取index处的元素
list.indexOf(Object a);//返回首次出现的索引
list.lastIndexOf(Object a);//返回最后一次出现的索引
list.remove(int index);//删除index处的元素
list.set(int index,Object a);//修改index处的元素为a
list.subList(int start,int end);//返回[start,end)处的子集
list.size();//长度
遍历方法
-
List list = new ArrayList();
//①迭代器遍历
Iterator ite = list.iterator();
while(ite.hasNext()){
System.out.println(ite.next());
}
//②使用增强for循环
for(Object i : list){
System.out.println(i);
}
//③使用普通for循环
for(int i = 0; i < list.size(); i++){
System.out.println(list.get(i));
}
④子接口二:Set接口(存储无序的、不可重复的数据)
三个实现类
-
|----HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值
-
|----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历在添加数据的同时,每个数据还维护了两个引用,记录此数据前一个数据和后一个数据。对于频繁的遍历操作,LinkedHashSet效率高于HashSet
-
|----TreeSet:可以照添加对象的指定属性,进行排序
以HashSet为例说明:
-
无序性:不等于随机性。存储的数据在底层数组中并非照数组索引的顺序添加,而是根据数据的哈希值决定的。
-
不可重复性:保证添加的元素照equals()判断时,不能返回true.即:相同的元素只能添加一个。
元素添加过程
-
我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值, 此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置)判断 数组此位置上是否已经元素: 如果此位置上没其他元素,则元素a添加成功。 --->情况1 如果此位置上其他元素b(或以链表形式存在的多个元素,则比较元素a与元素b的hash值: 如果hash值不相同,则元素a添加成功。--->情况2 如果hash值相同,进而需要调用元素a所在类的equals()方法: equals()返回true,元素a添加失败 equals()返回false,则元素a添加成功。--->情况2
对于添加成功的情况2和情况3而言:元素a 与已经存在指定索引位置上数据以链表的方式存储。 jdk 7 :元素a放到数组中,指向原来的元素。 jdk 8 :原来的元素在数组中,指向元素a 总结:七上八下
HashSet底层:数组+链表的结构。(前提:jdk7)
常用方法
-
Set接口中没额外定义新的方法,使用的都是Collection中声明过的方法。
存储对象所在类的要求
-
HashSet/LinkedHashSet:
要求:向Set(主要指:HashSet、LinkedHashSet)中添加的数据,其所在的类一定要重写hashCode()和equals() 要求:重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码
重写两个方法的小技巧:对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode值。
-
TreeSet:
1.自然排序中,比较两个对象是否相同的标准为:compareTo()返回0,不再是equals() 2.定制排序中,比较两个对象是否相同的标准为:compare()返回0,不再是equals() 3.向TreeSet中添加的数据,要求是相同类的对象 4.两种排序方式:自然排序(实现Comparable接口 和 定制排序(Comparator))
⑤Map接口
常用实现类
|----Map:双列数据,存储key-value对的数据 ---类似于高中的函数:y = f(x)
-
|----HashMap:作为Map的主要实现类;线程不安全的,效率高;存储null的key和value
-
|----LinkedHashMap:保证在遍历map元素时,可以照添加的顺序实现遍历。
-
原因:在原的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。
-
对于频繁的遍历操作,此类执行效率高于HashMap。
-
|----TreeMap:保证照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然排序或定制排序
-
底层使用红黑树
-
|----Hashtable:作为古老的实现类;线程安全的,效率低;不能存储null的key和value
-
|----Properties:常用来处理配置文件。key和value都是String类型
储存结构
Map中的key:无序的、不可重复的,使用Set存储所的key ---> key所在的类要重写equals()和hashCode() (以HashMap为例) Map中的value:无序的、可重复的,使用Collection存储所的value ---> value所在的类要重写equals() 一个键值对:key-value构成了一个Entry对象。 Map中的entry:无序的、不可重复的,使用Set存储所的entry
常用方法
-
put(Object key,Object value);//增 或 改,如果添加的key值本来没有,直接加入;如果已存在同样的key值,则覆盖value值
putAll(Map a);
remove(Object key);//根据key来删除数据
get(Object key);//根据key来查询数据
size();//长度
clear();//清空
isEmpty();//是否为空
equals(Object obj);
containsKey(Object key);//是否包含指定的key
containsValue(Object value);//是否包含指定的value,如果有重复的,查询到第一个就会停止
Set keySet();//返回所有key构成的Set集合
Collection values();//返回所有value构成的Collection集合
Set entrySet();//返回所有key-value对构成的Set集合