java中各种集合分类区别与遍历方式总结

一、简单的容器分类

在这里插入图片描述
你可以看到,其实只有四种容器:Map、List、Set和Queue,,它们各有两到三个实现。常见的用黑色粗线表示。
实线框表示普通的类,虚线框表示是一个接口,带有空心箭头的点线表示一个特定的类实现了该接口。实心箭头表示某个类继承了这个类。

二、几种常见的集合比较,该如何使用?

1、list也建立数字索引与对象的关联,因此,list和数组一样都是排好序的容器,但list可以自动扩充容量。
2、ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。 (LinkedList是双 向链表,有next也有previous),对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针;对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
3、Map是一种将对象与对象相关联的设计,它不是按照元素的添加顺序来存储对象的,所以是无序的,HashMap设计用来快速访问,TreeMap保持键始终处于排序状态,所以没有Hashmap快。HashMap中key值不可重复,允许key值为null,线程不安全。
4、Set不接受重复元素。HashSet提供最快的查询速度,TreeSet保持元素处于排序状态。
5、Queue(队列)使用较少,我在做在线人数监控的时候使用过队列来保持人数在指定范围内。

三、几种遍历方式总结

1、map的遍历方式

//1、通过获取所有的key按照key来遍历
//Set<Integer> set = map.keySet(); //得到所有key的集合
for (Integer in : map.keySet()) {
    String str = map.get(in);//得到每个key多对用value的值
}
//2、通过Map.entrySet使用iterator遍历key和value
Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
     Map.Entry<Integer, String> entry = it.next();
       System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//3、通过Map.entrySet遍历key和value,推荐,尤其是容量大时
for (Map.Entry<Integer, String> entry : map.entrySet()) {
    //Map.entry<Integer,String> 映射项(键-值对)  有几个方法:用上面的名字entry
    //entry.getKey() ;entry.getValue(); entry.setValue();
    //map.entrySet()  返回此映射中包含的映射关系的 Set视图。
    System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//4、通过Map.values()遍历所有的value,但不能遍历key
for (String v : map.values()) {
    System.out.println("value= " + v);
}

2、List的遍历方式

//1、foreach遍历迭代器
for(Iterator iterator = list.iterator();iterator.hasNext();){                    
    int i = (Integer) iterator.next();                   
    System.out.println(i);               
}
//2、使用迭代器的hasNext()方法
Iterator iterator = list.iterator();
while(iterator.hasNext()){
    int i = (Integer) iterator.next();
    System.out.println(i);
}
//3、foreach
for (Object object : list) { 
    System.out.println(object); 
}
//4、普通for循环
for(int i = 0 ;i<list.size();i++) {  
    int j= (Integer) list.get(i);
    System.out.println(j);  
}

3、集合类的通用遍历方式, 用迭代器迭代

Iterator it = list.iterator();
while(it.hasNext()) {
  Object obj = it.next();
}

4、总结

1.ArrayList由于使用数组实现,因此下标明确,最好使用普通循环。

2.for each 需要知道集合中元素类型,且不能操作指定的某个元素,效率稍低,代码简洁,使用率较高。

3、迭代器允许遍历过程中删除元素,而for循环不可以会报错。迭代器和for each都是根据集合长度自动遍历的,而普通for循环需要集合大小固定。

四、集合框架

Java中的集合框架大类可分为Collection和Map;两者的区别:
1、Collection是单列集合;Map是双列集合
2、Collection中只有Set系列要求元素唯一;Map中键需要唯一,值可以重复
3、Collection的数据结构是针对元素的;Map的数据结构是针对键的。

1、Collection

Collection包括两大体系,List和Set

(1)List
存取有序,有索引,可以根据索引来进行取值,元素可以重复
Arraylist: 底层是使用数组实现,所以查询速度快,增删速度慢,这是因为Arraylist在插入时,必须创建空间并将它所有的引用向前移动,这会随着Arraylist的尺寸增加产生高昂的代价。
LinkedList:是基于链表结构实现的,所以查询速度慢,增删速度快,LinkedList只需链接新的元素,而不必修改列表中的剩余元素。提供了特殊的方法,对头尾的元素操作(进行增删查),使用LinkedList来实现栈和队列;栈是先进后出,而队列是先进先出
stack.push(),stack.pop
最佳的做法可能是将Arraylist作为默认首选,当你的程序因为经常从表中间进行插入和移除元素时,导致程序变差,才去选择LinkedList。
(2)Set
元素不重复,存取无序,无下标
HashSet 存储无序,元素无索引,元素不可以重复.底层是哈希表.允许一个key为null
②LinkedHashSet 是基于链表和哈希表共同实现的,所以具有存取有序,元素唯一
TreeSet 存取无序,元素唯一,可以进行排序(排序是在添加的时候进行排序),不允许key为null
二叉树的存储过程:
如果是第一个元素,那么直接存入,作为根节点,下一个元素进来是会跟节点比较,如果大于节点放右边的,小于节点放左边;等于节点就不存储。后面的元素进来会依次比较,直到有位置存储为止
HashSet的性能基本上总是比TreeSet好,特别是在添加和查询元素时,而这两个操作也是最重要的操作。TreeSet存在的唯一原因是它可以维持元素的排序状态;所以只有当需要一个排好序的set时,才应该使用TreeSet。
TreeSet保证元素的唯一性是有两种方式:
1、自定义对象实现Comparable接口,重写comparaTo方法,该方法返回0表示相等,小于0表示准备存入的元素比被比较的元素小,否则大于0;
2、在创建TreeSet的时候向构造器中传入比较器Comparator接口实现类对象,实现Comparator接口重写compara方法。
如果向TreeSet存入自定义对象时,自定义类没有实现Comparable接口,或者没有传入Comparator比较器时,会出现ClassCastException异常
哈希表如何保证元素唯一呢 ? 底层是依赖 hashCode 和 equals 方法.

(3)队列(Queue)用法
队列是一种特殊的线性表,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。

LinkedList类实现了Queue接口,因此我们可以把LinkedList当成Queue来用。

mport java.util.LinkedList;
import java.util.Queue;
 
public class Main {
    public static void main(String[] args) {
        //add()和remove()方法在失败的时候会抛出异常(不推荐)
        Queue<String> queue = new LinkedList<String>();
        //添加元素
        queue.offer("a");
        queue.offer("b");
        queue.offer("c");
        queue.offer("d");
        queue.offer("e");
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("poll="+queue.poll()); //返回第一个元素,并在队列中删除
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("element="+queue.element()); //返回第一个元素 
        for(String q : queue){
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("peek="+queue.peek()); //返回第一个元素 
        for(String q : queue){
            System.out.println(q);
        }
    }
}

以上代码运行输出结果为:

a
b
c
d
e
===
poll=a
b
c
d
e
===
element=b
b
c
d
e
===
peek=b
b
c
d
e

offer,add 区别:

一些队列有大小限制,因此如果想在一个满的队列中加入一个新项,多出的项就会被拒绝。

这时新的 offer 方法就可以起作用了。它不是对调用 add() 方法抛出一个 unchecked 异常,而只是得到由 offer() 返回的 false。

poll,remove 区别:

remove() 和 poll() 方法都是从队列中删除第一个元素。remove() 的行为与 Collection 接口的版本相似, 但是新的 poll() 方法在用空集合调用时不是抛出异常,只是返回 null。因此新的方法更适合容易出现异常条件的情况。

peek,element区别:

element() 和 peek() 用于在队列的头部查询元素。与 remove() 方法类似,在队列为空时, element() 抛出一个异常,而 peek() 返回 null.

2、Map

Map是一个双列集合,其中保存的是键值对,键要求保持唯一性,值可以重复
键值是一一对应的,一个键只能对应一个值,
(1)HashMap 是基于哈希表结构实现的,所以存储自定义对象作为键时,必须重写hasCode和equals方法。存取无序的 允许一个key为null
(2)TreeMap给TreeMap集合中保存自定义对象,自定义对象作为TreeMap集合的key值。由于TreeMap底层使用的二叉树,其中存放进去的所有数据都需要排序,要排序,就要求对象具备比较功能。对象所属的类需要实现Comparable接口。或者给TreeMap集合传递一个Comparator接口对象,不允许key为null
(3)LinkedHashMap 用法跟HashMap基本一致,它是基于链表和哈希表结构的所以具有存取有序,键不重复的特性
当使用Map时。你的第一选择应该是HashMap,只有在你要求Map始终保持有序时,才需要使用TreeMap。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值