目录
集合
首先,集合分两大块,实现Collection接口的大类,以及Map类。Collection大类中元素是单个存储的,在Map中元素是以key-value方式存储的。
Collection
实现Collection接口的大类中又包含List类和Set类。最大的区别在于List内的元素可以重复,Set集合的内容不能重复,即可以实现去重功能。,需要注意的是,Set中是重复元素存不进去
List集合
List集合中最常用的就是ArrayList和LinkedList,前者的存储方式是基于数组实现的,后者是基于类似C语言中的链表实现的。其实在List中还有一个Vector类,但它的功能于ArrayList相同,且效率较低,所以被淘汰,如今基本没什么人用。
Set集合
在Set集合中又分为HashSet和TreeSet。
HashSet是基于哈希表实现的存储,即对要存元素的哈希值进行一些操作,最终得到一个存储位置,进行存放,这就导致了HashSet存储元素是无序的,在引申一下,在HashSet下还有一个LinkedHashSet,于LinkedList一样,同样是基于链表实现的,它能够做到以存入顺序有序。
TreeSet是根据排序二叉树原理存储的,即能够实现有序存储,小的在前,大的在后,但若是需要存储一些自定义类的元素,需要自己重写比较器(内外都可以,在调用时区分)。
Map集合
与Set类似,Map同样也分两类,HashSet于TreeSet,基于hashSet同样也有一个LinkesHashSet。在性质上于Set集合一致。同时Map还有一个Hashtable集合,它与HashMap的关系与Vector类和ArrayList的关系相同
Map接口并没有直接继承自任何类。Map
接口是一个独立的接口,用于表示键值对的集合。然而,Map
接口的常见实现类HashMap
、TreeMap
、LinkedHashMap
等都是直接或间接地继承自AbstractMap
类。AbstractMap
类是一个抽象类,提供了Map
接口的基本实现。它实现了Map
接口中的大部分方法,为Map
的具体实现类提供了一些通用的功能。Map也有不能存储重复元素的性质,但这个不能重复是指key不能重复,value仍旧可以相同。而且这个key一般是以基本数据类型的包装类为主。
关于去重以及排序问题
不论是HashSet还是HashMap都是由哈希表实现的,存储的时候会比较元素的哈希值,判断没有后才会存储,这样就保证了唯一性,这此种存法会导致其内元素无序。
对于Linked实现的LinkedList、LinkedHashSet和LinkedHashMap,因为是链表实现的存储,能够实现根据存入顺序有序,即存入顺序是何样,其内部顺序就是何样。
而TreeSet和TreeMap则是通过比较器实现去重以及排序问题,通过返回值的是否为0和正负判断是否存储,以及是往前存,还是往后存。
而且Map集合在存储相同元素时会对valu值进行更新,即存储新的元素,原先集合内部有的会被替换掉。
关于遍历问题
下面以ArrayList为例,设list为一个ArrayList集合
如下:
List list = new ArrayList();
迭代器遍历(Collection大类才可以)
Collection接口有迭代器,实现Collection类的都可以通过迭代器遍历;即只有List和Set可以通过迭代器遍历,Map做不到。
如下:
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
迭代器ListIterator
因为Iterator 迭代器无法在遍历时对list集合进行插入操作
但ListIterator 可以
具体用法为
ListIterator<String> it = list.listIterator();
while(it.hasNext()){
if("cc".equals(it.next())){
it.add("kk");
}
}
同时ListIterator还可以逆向遍历
while(it.hasPrevious()){
System.out.println(it.previous());
}
*previous()与next()共享指针
所以要是同时调用他们两个,会死循环
forEach遍历(List,Set集合)
List、Set还可以类似数组,直接用for-each进行遍历,无需借助迭代器
如下:
for(Object obj:list){
System.out.println(obj);
}
ForEach循环还能与迭代器结合起来
如下:
for(Iterator<String> it = list.iterator();it.hasNext();){
System.out.println(it.next());
}
这种方式会更好些,节省内存
需要说明的是,在Java中使用增强for循环(也称为for-each循环)可以遍历List或Set,即使它们没有加泛型也是可以的。在没有加泛型的情况下,增强for循环会将元素作为Object类型处理,因此仍然可以使用增强for循环来遍历集合中的元素。然而,由于没有泛型的支持,可能需要在处理元素时进行类型转换。
For循环遍历(只有List)
通过普通for循环和索引i,可以遍历List集合并访问每个元素。
如下:
for(int i = 0;i<list.size();i++){
System.out.println(list.get(i));
}
然而,对于Set接口来说,普通for循环无法直接通过索引来访问元素,因为Set是无序集合,没有像List那样的索引顺序。因此,普通for循环通常不适用于Set集合的遍历。对于Set集合,仍然建议使用增强for循环或迭代器来进行遍历操作。
总结来说,普通for循环适用于List集合,但对于Set集合,通常建议使用增强for循环或迭代器来进行遍历操作。
Map遍历
假设这里有一个HashMap的集合map如下,其key值为String类型,value为Integer类型
Map<String,Integer> map = new HashMap<>();
通过获取key遍历
通过语句
Set<String> set = map.keySet();
获取key值,返回的是一个Set集合,之后后可以通过循环遍历,通过key值访问其value
如:
for(String s:set){
System.out.println(map.get(s));
}
通过获取实体类遍历
通过语句:
Set<Map.Entry<String, Integer>> entries = map.entrySet();
获取实体对象的Set集合,这个Entry对象是Map接口下的。使用方法如上,需要指明key-value的类型;其内主要存储的就是key值和value值。
又因为是个Set集合,就可以通过循环,或迭代器等遍历访问,如以下例子,就是通过增强for访问
for(Map.Entry<String, Integer> e:entries){
System.out.println(e.getKey()+"----"+e.getValue());
}
通过Collection获取value遍历
Collection<Integer> values = map.values();
这个语句将 map
中所有的值(value
)以 Collection
类型存储在变量 values
中。具体来说,map.values()
返回一个 Collection
视图,其中包含了 map
中所有的值。这个视图可以被当作一个集合来操作,但它并不是一个独立的集合实例,而是与原始的 map
相关联的。
之后便可以通过遍历values去访问所有的map中的value
如下:
for(Integer i:values){
System.out.println(i);
}