Java—集合

集合

在编程中,常常需要存放多个数据。从传统意义上讲,数组是我们一个很好的选择,前提是我们事先已经明确知道我们要保存的对象的数量。一旦在数组初始化时制定了这个数组长度,这个数组长度就是不可变的,如果我们需要保存一个可以动态增长的数据(在编译时还无法确定具体的数量),java的集合类就是一个很好的设计方案

集合类主要负责保存,盛装其他数据,因此集合类也被称为容器类。所有的集合类都位于java.util包下,后来为了处理多线程环境下的并发安全问题,java5还在java.util.concurrent包下提供了一些多线程支持的集合类

  • 下面是集合类的关系图

image.png

接下来我们一次介绍各种集合及其实现类

1.List

  • List集合代表一个元素有序,可重复的集合,集合中每个元素都有其对应的顺序索引。

    • 1> ArrayList: ArrayList是基于数组实现的List类,它封装了一个动态增长的,允许再分配的Object[]数组
    • 2> Vector: Vector和ArrayList在用法上几乎完全相同,但它是线程安全的,所以效率会比ArrayList的效率低。不过现在几乎已经淘汰了
    • 3> LinkedList:底层的数据结构是链表,我们都知道链表和数组的区别,所以LinkedList与ArrayList的区别也很清晰:ArrayList 查询快,但插入删除慢。LinkedList 查询慢,插入与删除较快。我们要根据具体数据操作需求来选择集合类型。
    • 4> Queue:Queue用来模拟 “队列”这种数据结构,队列的头部存放着队列中存放时间最长的元素,队列的尾部保存着队列中存放时间最短的元素。新元素插入到队列的尾部

    • PriorityQueue: “优先队列”,其中队列元素的顺序并不是按照加入队列的顺序,而是按着元素的大小进行重新排序

    • Deque:Deque接口代表一个 “双端队列”,双端队列可以同时从两端来添加,删除元素,因此Deque的实现类即可以当成队列来使用,又可以当成栈来使用。ArrayDeque 是一个基于数组的双端队列,和ArrayList类似,它们的底层都采用一个动态的、可重分配的Object[]数组来存储集合元素,当集合元素超出该数组的容量时,系统会在底层重新分配一个Object[]数组来存储集合元素。另外,LinkedList也可以用作双端队列

2.Set

  • 与List相对应,Set集合是元素无序,不可重复的集合。Set判断两个对象相同不使用 “==”运算符,而是根据equals方法,也就是说,我们在加入一个新元素的时候,如果这个新元素对象和Set中已有的对象进行equals方法比较都返回false,则Set接受这个新元素对象,否则拒绝。
  • 也正是因为Set的这个制约,所以在应用Set集合时,应注意两点:
    • 1> 为集合里的元素的实现类实现一个有效的equals(Object)方法.
    • 2> 对Set构造器,传入的Collection参数集合对象中不能包含重复的元素
  • 1> HashSet: HashSet是Set接口的典型实现,HashSet使用HASH算法来存储集合中的元素,因此有有良好的存取和查找性能,当向HashSet中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到hashCode值,然后根据HashCode值决定该对象在HashSet中的存储位置。注意:如果两个元素用equals方法比较结果是true,那他们用hashCode()方法求得的hashCode值也一定相等。

    • LinkedHashSet: LinkedHashSet集合也是根据元素的hashCode值来决定元素的存储位置,但和HashSet不同的是,它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。当遍历LinkedHashSet集合里的元素时,LinkedHashSet将会按元素的添加顺序来访问集合里的元素。
  • 2> SortedSet: 此接口主要用于排序操作,即实现此接口的子类都属于排序的子类。

    • TreeSet: 是SortedSet接口的实现类,通过一边添加元素一边排序,使整个集合有序。 底层实现:红黑树
  • 3> EnumSet: EnumSet是一个专门为枚举类型设计的集合类,EnumSet中所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式地指定。EnumSet的集合元素也是有序的,它以枚举值在Enum类中的定义顺序来决定集合元素的顺序


3.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 不能重复),value集的存储形式和List非常类似
  • 1> HashMap:和HashSet集合不能保证元素顺序一样,HashMap也不能保证key-value对的顺序。并且类似于HashSet判断两个key是否相等的标准也是:两个key通过equals方法比较返回true,同时两个key的hashCode值也必须相等

    • LinkedHashMap: LinkedHashMap也用双向链表维护key-value对的次序,该链表负责维护Map的迭代顺序,与key-value对的插入顺序一致。
  • 2> Hashtable:线程安全相关,不过在java新增了java.util.concurrent包后就被淘汰了。

    • Properties : Properties对象的key-value键值对都只能是String类型,多用来加载资源文件。
  • 3> TreeMap: 红黑树结构,每个key-value对即作为红黑树的一个节点。TreeMap存储key-value对时,根据key对节点进行排序。TreeMap可以保证所有的key-value对处于有序状态。同样,TreeMap也有两种排序方式:自然排序,定制排序

  • 4> WeakHashMap:WeakHashMap的用法与HashMap的用法基本相似。区别在于,HashMap的key保留了对实际对象的 “强引用”,这意味着只要该HashMap对象不被销毁,该HashMap所引用的对象就不会被垃圾回收,但WeakHashMap的key只保留了对实际对象的弱引用,这意味着如果WeakHashMap对象的key所引用的对象没有被其他强引用变量所引用,则这些key所以用的对象可能被垃圾回收,当垃圾回收了该key所对应的实际对象后,WeakHashMap也可能自动删除这些key所对应的key-value对

  • 5> IdentityHashMap:与HashMap的实现机制基本类似,但在IdentityHashMap中,当且仅当两个key是同一对象的引用(key1 == key2)时,IdentityHashMap才认为两个key相等。

  • 6> EnumMap是一个与枚举类一起使用的Map实现,EnumMap中的所有key都必须是单个枚举类的枚举值。创建EnumMap时必须显式或隐式指定它对应的枚举类。EnumMap根据key的自然顺序(即枚举值在枚举类中的定义顺序)排序

4.迭代器

进入Collection的jdk源码我们能看到
public interface Collection<E> extends Iterable<E>
这也就说明,所有的集合(除Map系列的集合),都要实现这个接口,进入到这个接口的jdk源码我们会看到这两个方法
Iterator<T> iterator();
default void forEach(Consumer<? super T> action){...}
一个返回类型为Iterator的方法,和一个接口中的默认forEach方法(这也就说明了为什么Collection的实现类可以使用增强for来遍历集合)。
接下来我们来说明Iterator和Iterable的区别。
  • Iterator 是java.util包下的一个接口,主要有以下几个方法
boolean hasNext();
E next();
void remove()
  • Iterable 存在于java.lang包下,只要实现了这个接口,就可以通过返回iterator对象或forEach来遍历集合。

5.排序

猜你喜欢

转载自blog.csdn.net/wintershii/article/details/81253593
今日推荐