章
目
录
Java集合框架包括接口和类,用于处理不同类型的集合,如列表、集合、映射、栈和队列等。
这些现成的集合类解决了许多常见问题,其中我们需要处理同质和异质对象的组。常见的操作包括添加、删除、更新、排序、搜索以及更复杂的算法。这些集合类使用集合API提供了对所有这些操作的非常透明的支持。
1.Java集合层次结构
通过核心接口可以更好地理解集合框架。集合类实现这些接口并提供具体的功能。
1.1. 集合(Collection)
集合接口位于层次结构的根部。集合接口提供了所有通用方法,所有集合类必须支持(或引发UnsupportedOperationException异常)。它扩展了Iterable接口,该接口添加了使用“for-each循环”语句遍历集合元素的支持。
除Map之外的所有其他集合接口和类都要么扩展要么实现这个接口。例如,列表(有索引、有序)和集合(有序)接口实现了这个集合。
1.2. 列表(List)
列表表示有序的元素集合。使用列表,我们可以通过它们在列表中的整数索引(位置)访问元素,并搜索列表中的元素。索引从0开始,就像数组一样。
实现List接口的一些有用的类包括ArrayList、CopyOnWriteArrayList、LinkedList、Stack和Vector。
1.3. 集合(Set)
Set集合表示独特元素的集合。Set集合不允许重复的元素。Set接口不保证存储元素的顺序;尽管某些Set实现按照它们的自然顺序存储元素并保证这个顺序。
实现Set接口的一些有用的类包括ConcurrentSkipListSet、CopyOnWriteArraySet、EnumSet、HashSet、LinkedHashSet和TreeSet。
1.4. 映射(Map)
映射接口使我们能够以键-值对(键应该是不可变的)的形式存储数据。一个映射不能包含重复的键;每个键最多可以映射到一个值。
映射接口提供了三个集合视图,允许将映射的内容视为一组键、值的集合或键-值映射的集合。某些映射实现,比如TreeMap类,对它们的顺序提供了特定的保证;而其他的,比如HashMap类,不提供。
实现Map接口的一些有用的类包括ConcurrentHashMap、ConcurrentSkipListMap、EnumMap、HashMap、Hashtable、IdentityHashMap、LinkedHashMap、Properties、TreeMap和WeakHashMap。
1.5. 栈(Stack)
Java的Stack接口代表了一个经典的堆栈数据结构,其中元素可以被推送到后进先出(LIFO)的对象堆栈中。在堆栈中,我们将一个元素推送到堆栈的顶部,稍后再从堆栈的顶部弹出它。
1.6. 队列(Queue)
队列数据结构用于在消费者线程处理之前保存元素(由生产者线程放置)。除了基本的集合操作,队列还提供了额外的插入、提取和检查操作。
队列通常以FIFO(先进先出)的方式对元素进行排序,但不一定如此。这种情况的一个例外是优先队列,它根据提供的比较器或元素的自然顺序来排序元素。
一般来说,队列不支持阻塞的插入或检索操作。阻塞队列实现类实现BlockingQueue接口。
实现Queue接口的一些有用的类包括ArrayBlockingQueue、ArrayDeque、ConcurrentLinkedDeque、ConcurrentLinkedQueue、DelayQueue、LinkedBlockingDeque、LinkedBlockingQueue、LinkedList、LinkedTransferQueue、PriorityBlockingQueue、PriorityQueue和SynchronousQueue。
1.7. 双端队列(Deque)
双端队列(发音为“deck”)支持在两端插入和移除元素。当双端队列用作队列时,会出现FIFO(先进先出)行为。当双端队列用作堆栈时,会出现LIFO(后进先出)行为。
这个接口应该优先使用,而不是传统的Stack类。当双端队列用作堆栈时,元素从双端队列的开头推送和弹出。
一些常见的实现这个接口的类包括ArrayDeque、ConcurrentLinkedDeque、LinkedBlockingDeque和LinkedList。
2.Java集合和泛型
泛型提供类型安全。它检测不兼容的类型(在方法参数中)并防止运行时的ClassCastException。我们还可以在Java集合中定义一个只能存储特定类型对象的集合类。其他类型应该被禁止。这是通过泛型实现的。
在给定示例中允许前两个add()方法。第三个方法不会编译并会报错 – “HashMap<Integer,String>类型中的put(Integer, String)方法不适用于参数(String, String)”。“泛型”有助于早期检测不兼容的类型,以防止运行时的不可预测行为。
Generic HashMap
HashMap<Integer, String> map = new HashMap<>();
map.put(1, "A"); //允许
map.put(2, "B"); //允许
map.put("3", "C"); //不允许 -因为key是String类型
3.equals() 和 hashCode() 方法
许多集合类提供特定的功能,如排序元素、不重复元素等。为了实现这种行为,添加的元素(对象)必须正确实现equals()和hashCode()方法。
所有Java包装类和String类都使用它们自己的具体实现覆盖了这些函数,因此它们在这些集合中的行为是正确的。我们还需要确保这些函数在我们自定义的用户定义类中正确地被覆盖。
SortedSet<Integer> sortedSet = new TreeSet<>();
sortedSet.add(2);
sortedSet.add(1);
sortedSet.add(1);
sortedSet.add(3);
System.out.println(sortedSet); //[1,2,3]
4.Java 8的变化
Java 8是一个重大的发布,引入了Java中的lambda式编程。集合类也因此得到了改进。例如,我们可以在一行代码中遍历集合并对集合的所有元素执行操作,使用forEach语句。
ArrayList<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.forEach(System.out::print);
5.Java集合的好处
5.1. 一致和可重用的API
这就是一个框架的作用。它提供了一组一致的类方法,可以用来一次又一次地解决相似的问题,而不会得到不可预测的结果。Java集合框架也一致地帮助解决与对象组相关的常见问题。
所有集合类都具有一致的实现,并提供了一些常见的方法,如add、get、put、remove等。无论你处理什么类型的数据结构,这些方法都会根据底层实现工作,并且以透明的方式执行操作。
5.2. 减少开发时间
一个常见且可预测的框架总是减少了开发时间,有助于以迅速的方式编写应用程序。Java集合还有助于执行一些最常见的与对象和集合相关的任务,从而提高了时间效率。
5.3. 性能
Java集合API是由业界一些最聪明的头脑编写的,它们在大多数情况下性能卓越。Oracle和非常热情的Java开发者社区的持续开发工作有助于不断改进。
5.4. 清晰的代码
这些API是以所有良好的编程实践编写的,并且文档非常完善。它们遵循整个Java集合框架的某个标准。这使得程序员的代码看起来整洁而干净。
由于类名和方法名一致,代码也更容易阅读。