Java集合系列之Collection与Map接口宏观把控

Java集合系列之Collection与Map接口宏观把控

Hello,大家好,元旦快到了,这里提前祝大家元旦快乐,出行注意安全,回家的小伙伴能早日和家人见面,开开心心过元旦。Ok,切入主题,这篇文章,我本人觉得还是比较重要的,因为我准备在宏观上把Java集合这一块给描述清楚。老套路,文章结构:

  1. Java集合类之间的继承关系
  2. 各个宏观模块介绍
  3. 集合与集合之前的转换,集合与数组之间的转换

1. Java集合类之间的继承关系

Java的集合类主要由两个接口派生而出:Collection和Map,Collection和Map是Java集合框架的根接口。来两张图:

图中标红圈的表示我们经常用的集合类。

2. 各个宏观模块介绍

2.1 Collection接口

Collection接口是Set,Queue,List的父接口。Collection接口中定义了多种方法可供其子类进行实现,以实现数据操作。

可以看出Collection用法有:添加元素,删除元素,返回Collection集合的个数以及清空集合等。
其中重点说下iterator()方法,该方法的返回值是Iterator。
这个迭代器是这样来的

public interface Collection<E> extends Iterable<E> 
复制代码

使用样例:

Collection<Day> days = new ArrayList<Day>();
Iterator<Day> iterator = days.iterator();
        while(iterator.hasNext()){//判断是否有下一个元素
            Day next = iterator.next();//取出该元素
            //逐个遍历,取得元素后进行后续操作
            .....
        }
复制代码

顺便说一下,在遍历Map集合的时候,虽然Map没有继承Iterable,不过没有关系,可以转换成set,然后再遍历:

  • 第一种(据说是效率高于第二种,小弟也没验证过):
Map map = new HashMap();
    Iterator iter = map.entrySet().iterator();
    while (iter.hasNext()) {
        Map.Entry entry = (Map.Entry) iter.next();
        Object key = entry.getKey();
        Object val = entry.getValue();
    }
复制代码
  • 第二种:
Map map = new HashMap();
Iterator iter = map.keySet().iterator();
    while (iter.hasNext()) {
    Object key = iter.next();
    Object val = map.get(key);
}
复制代码

其次,需要注意的是,在使用Iterable遍历Collection时,当Collection内部的元素为对象类型时,.next返回的是指针。也就是说是浅拷贝。

2.1.1 Set集合

Set集合类似于一个罐子,"丢进"Set集合里的多个对象之间没有明显的顺序。Set继承自Collection接口,不能包含有重复元素(记住,这是整个Set类层次的共有属性)。Set判断两个对象相同不是使用"=="运算符,而是根据equals方法。也就是说,我们在加入一个新元素的时候,如果这个新元素对象和Set中已有对象进行注意equals比较都返回false,则Set就会接受这个新元素对象,否则拒绝。
因为Set的这个制约,在使用Set集合的时候,应该注意两点:

  • 为Set集合里的元素的实现类实现一个有效的equals(Object)方法。
  • 对Set的构造函数,传入的Collection参数不能包含重复的元素

API层面,Set集合与Collection集合基本相同,没有提供任何额外的方法。实际上Set就是Collection,只是行为略有不同(Set不允许包含重复元素)。

2.1.2 List集合

List集合代表一个元素有序、可重复的集合,集合中每个元素都有其对应的顺序索引。List集合允许加入重复元素,因为它可以通过索引来访问指定位置的集合元素。List集合默认按元素的添加顺序设置元素的索引.

API层面:List作为Collection接口的子接口,可以使用Collection接口里的全部方法。而且由于List是有序集合,因此List集合里增加了一些根据索引来操作集合元素的方法。如下:

  • void add(int index, Object element): 在列表的指定位置插入指定元素.
  • boolean addAll(int index, Collection<? extends E> c): 将集合c 中的所有元素都插入到列表中的指定位置index处。
  • Object get(index):返回列表中指定位置的元素。
  • int indexOf(Object o):返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
  • int lastIndexOf(Object o):返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
  • Object remove(int index): 移除列表中指定位置的元素。
  • Object set(int index, Object element):用指定元素替换列表中指定位置的元素。
  • List subList(int fromIndex, int toIndex):返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的所有集合元素组成的子集。
2.1.3 Queue集合

Queue用于模拟"队列"这种数据结构(先进先出FIFO)。队列的头部保存着队列中存放时间最长的元素,队列的尾部保存着队列中存放时间最短的元素。新元素插入(offer)到队列的尾部,访问元素(poll)操作会返回队列头部的元素,队列不允许随机访问队列中的元素。

可以看到,新增了offer和poll用来描述队列这种语义

2.2 Map接口

Map用于保存具有"映射关系"的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,另外一组值用于保存Map里的value。key和value都可以是任何引用类型的数据。Map的key不允许重复,即同一个Map对象的任何两个key通过equals方法比较结果总是返回false。关于Map,我们要从代码复用的角度去理解,java是先实现了Map,然后通过包装了一个所有value都为null的Map就实现了Set集合

  • Map的这些实现类和子接口中key集的存储形式和Set集合完全相同(即key不能重复)
  • 与Set集合的关系:如果把Map里的所有key放在一起看,它们就组成了一个Set集合(所有的key没有顺序,key与key之间不能重复),实际上Map确实包含了一个keySet()方法,用于返回Map里所有key组成的Set集合。

API:

Map集合最典型的用法就是成对地添加、删除key-value对,然后就是判断该Map中是否包含指定key,是否包含指定value,也可以通过Map提供的keySet()方法获取所有key组成的集合,然后使用foreach循环来遍历Map的所有key,根据key即可遍历所有的value

3. 集合与集合之前的转换,集合与数组之间的转换

3.1 集合与数组之间的转换

  • 数组转换成List:Array.asList()可以将一个数组转换成一个List.
  • 集合转换成数组:Collection接口中定义了toArray方法.

3.1 集合与集合之间的转换

Map--》Collection:
Map.keySet(),entrySet(),.values().三个API

List《---》Set《---》Queue:

        //Set--》List
        List<String> list3 = new ArrayList<String>(new HashSet<String>());   
        //List--》Set
        Set<String> set = new HashSet<String>(new ArrayList<String>());  
复制代码

说白了,都是通过构造方法来转换的.

转换这一块给一个参考博客:

结语

好了,宏观角度的Collection,Map算是给大家说清楚了,包括Collection下的子接口要实现的语义(子接口实现的特有方法)。然后集合之间的转换等等,我觉得宏观上是比较重要的,也希望大家这一块掌握好。Over,Hava a good day .元旦快乐,大家。