浅谈 Java 集合框架

简介: Java 最初版本只提供了最初的几个 Java 集合框架个类:• Vector• Stack• Hashable• BitSet• Enumeration其中 Enumeration 接口提供了一种用于访问任意容器中各个元素的抽象机制。Java 集合类库将接口( interface )与实现(implementation)分离。

队列是如何分离的

队列是如何分离的队列涉及的几个操作:

• 在队尾添加元素

• 在队头删除元素

• 查找队列中元素的个数


特点:先入先出队列的接口:

public interface Queue<E> // a simplified form of the interface in the stardard library
{
  void add(E element);
  E remove();
  int size();
}


在数据结构课中,队列通常有两种实现方式:


  1. 使用循环数组;但这种方式的局限是队列的长度有限。
  2. 使用链表代码表示如下:
public class CircularArrayQueue<E> implements Queue<E>  // not an actual library class
{
    private int head;
    private int tail;
    CircularArrayQueue(int capacity) {...}
    public void add(E element) {...}
    public E remove() {...}
    public int size() {...}
    private E[] elements;
}
public class LinkedListQueue<E> implements Queue<E>  // not an actual library class
{
    private Link head;
    private Link tail;
    LinkedListQueue() {...}
    public void add(E element) {...}
    public E remove() {...}
    public int size() {...}
}

注释:实际上,Java 类库没有名为 CirclularArrayQueue 和 LinkedListQueue 的类。这里只是以这些类作为示例来解释集合接口与实现在概念上的区分。


Queue 的使用

假设定义了上述的 CircularArrayQueueLinkedListQueue 之后,就可以直接使用:

Queue<Customer> expressLane = new CircularArrayQueue<>(100);
expressLane.add(new Customer("Harry")
Queue<Customer> expressLane = new LinkedListQueue<>();
expressLane.add(new Customer("Bug")

循环数组要比链表高效,因此多数人优先选择循环数组。

但是循环数组是一个有界数组,即容量有限。如果使用的对象数量没有上限,最好使用链表实现。


Collection 接口


所有通用集合实现都有一个带有 Collection 参数的构造函数,此构造函数初始化新集合以包含指定集合中的所有元素,即它允许转换集合的类型。

如把一个 Collection<String> s,它可以转化成 List、Set 或其他类型的 Collection。如:

List<String> s = new ArrayList<String>(c);


Collection 接口包含执行基本操作的方法:

  • int size()
  • boolean isEmpty()
  • boolean contains(Object element
  • boolean add(E element)
  • boolean remove(Object element)
  • Interator<E> interator()


Collection 接口还包含对整个集合进行操作的方法:

  • boolean containsAll(Collection<?> c)
  • boolean addAll(Collection<? extends E> c)
  • boolean removeAll(Collection<?> c)
  • boolean retainAll(Collection<?> c)
  • void clear()

Collection 接口还存在用于数组操作的附加方法,例如:

  • Object[] toArray()
  • <T> T[] toArray(T[] a)


JDK 8 及更高版本中,Collection 接口还公开方法 Stream<E> stream() 和 Stream<E> parallelStream(),帮助从底层集合中获取顺序或并行流。

public interface Collection<E> {
  boolean add(E element);
  Interator<E> iterator();  // 返回一个用于访问集合中各个元素的迭代器
}


add 方法用于向集合中添加元素。如果成功添加元素改变了集合就返回 true;如果集合没有发生改变就返回 false。比如在集合( set )中添加一个对象,如果这个元素在集合中已经存在,这时 add 方法就没有奏效,因为集合中不允许有重复的对象。


interator 方法用于返回一个实现了 Interator 接口的对象,可以使用这个迭代器对象依次访问集合中的元素。


集合遍历接口--迭代器

Iterator 接口包含 4 个方法:

public interface Interator<E> {
  E next(); // 返回将要访问的下一个对象。如果已经到达了集合的末尾,将抛出一个 NoSuchElement-Exception
  boolean hasNext();  // 如果存在另一个可访问的元素,返回 true
  void remove();  // 删除上次访问的对象。这个方法必须紧跟在访问一个元素之后执行。如果上次访问之后集合已经发生了变化,这个方法将会抛出一个 IllegalStateException
  default void forEachRemaining(Consumer<? super E> action); // 访问元素,并传递到指定的动作,直到再没有更多元素,或者这个动作抛出一个异常
}


通过反复调用 next 方法,可以逐个访问集合中的每个元素。但是,如果到达了集合的末尾,next 方法将抛出一个 NoSuchElementException。因此,在需要调用 next 之前调用 hasNext 方法。

hashNext 如果迭代器对象还有多个可以访问的元素,这个方法就返回 true。

Collection<String> c = ...;
Interator<String> iter = c.iterator();
while (iter.hasNext()) {
  String element = iter.next();
  // do something with element
}


for each 循环可以更加简练地表达同样的循环操作:

for (String element : c) {
  // do something with element
  System.out.Println(element);
}


for each 循环可以处理任何实现了 Iterable 接口的对象,这个对象只包含一个抽象方法:

public interface Iterable<E> {
  Iterator<E> iterator();
}


JDK8 及更高版本中,迭代集合的首选方法是获取流并对其执行聚合操作。聚合操作需要与 Lambda 表达式结合使用,以使用较少的代码使编程更具表现力。

myShapeCollection.stream()
  .filter(e -> e.getColor() == Color.RED)
  .forEach(e -> System.out.Println(e.getName()));


访问元素的顺序取决于集合类型。

  • 如果迭代处理一个 ArrayList,迭代器索引从 0 开始,没迭代一次,索引值加 1 。
  • 如果访问 HashSet 中的元素,会按照一种基本上随机的顺序获得元素。(每一次访问的顺序都是唯一的)


Iterator 接口的 remove 方法将会删除上次调用 next 方法时返回的元素。目的是:删除某个元素前最该先看一下这个元素。


集合接口批量操作

批量操作对整个集合执行操作。包含基本的方法有:

  • contailsAll : 如果目标 Collection 包含指定 Collection 中的所有元素,就返回 true。
  • addAll : 将指定 Collection 中的所有元素添加到目标 Collection。
  • removeAll : 从目标 Collection 中删除包含在指定 Collection 中的所有元素。
  • retainAll : 从目标 Collection 中删除所有所有未包含在指定 Collection 中删除所有未包含在指定 Collection 中的元素。
  • clear : 从集合中删除所有元素。


如,检测任意集合是否包含指定元素的泛型方法:

public static <E> boolean contains(Collection<E> c, Object obj) {
    for (E element : c)
    if (element.equals(obj))
        return true;
    return false;
}


其他方法

还有一些实用方法非常有用,应该将它们提供给用户实用。下面列举一部分:

int size()  // 返回当前存储在集合中的元素个数
boolean isEmpty() // 如何集合中没有元素,返回 true
boolean contains(Object obj)  // 如果集合中包含了一个与obj相等的元素,返回true
boolean equals(Object other)  // 如果集合与 other 集合相等,返回true
boolean add(E element) // 将一个元素添加到集合中。由于这个调用改变了集合,返回 true
boolean addAll(Collection<? extends E> from) // 将 other 集合中的所有元素添加到这个集合。如果由于这个调用改变了这个集合,返回true
boolean remove(Object obj)  // 从这个集合中删除等于 obj 的对象。如果有匹配的对象被删除,返回true
boolean removeAll(Collection<?> c) // 从这个集合中删除obj集合中存在的所有元素。如果这个调用改变了集合,返回true
default boolean removeIf(Predicate<? super E> filter // JDK8, 从这个集合中删除filter返回true的所有元素,如果因为这个调用改变了集合,返回true
void clear() // 从这个集合中删除所有的元素
boolean retainAll(Collection<?> c) // 从这个集合中删除所有与other集合元素不同的元素。如果由于这个调用改变了集合,返回true
Object[] toArray() // 返回这个集合中的对象的数组
<T> T[] toArray(T[] arrayToFill)


<T> T[] toArray(T[] arrayToFill) :返回这个集合中的对象的数组。如果 arrayToFill 足够大,就将集合中的元素填入这个数组中,剩余空间填补 null;否则,分配一个新数组,其成员类型与 arrayToFill 的成员类型相同,其长度等于集合的大小,并填充集合元素。

相关文章
|
25天前
|
Java 数据库
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
|
25天前
|
消息中间件 Java Kafka
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
|
1月前
|
JSON Java Apache
非常实用的Http应用框架,杜绝Java Http 接口对接繁琐编程
UniHttp 是一个声明式的 HTTP 接口对接框架,帮助开发者快速对接第三方 HTTP 接口。通过 @HttpApi 注解定义接口,使用 @GetHttpInterface 和 @PostHttpInterface 等注解配置请求方法和参数。支持自定义代理逻辑、全局请求参数、错误处理和连接池配置,提高代码的内聚性和可读性。
130 3
|
8天前
|
存储 缓存 安全
Java 集合江湖:底层数据结构的大揭秘!
小米是一位热爱技术分享的程序员,本文详细解析了Java面试中常见的List、Set、Map的区别。不仅介绍了它们的基本特性和实现类,还深入探讨了各自的使用场景和面试技巧,帮助读者更好地理解和应对相关问题。
29 5
|
20天前
|
存储 缓存 安全
Java 集合框架优化:从基础到高级应用
《Java集合框架优化:从基础到高级应用》深入解析Java集合框架的核心原理与优化技巧,涵盖列表、集合、映射等常用数据结构,结合实际案例,指导开发者高效使用和优化Java集合。
31 4
|
1月前
|
人工智能 前端开发 Java
基于开源框架Spring AI Alibaba快速构建Java应用
本文旨在帮助开发者快速掌握并应用 Spring AI Alibaba,提升基于 Java 的大模型应用开发效率和安全性。
基于开源框架Spring AI Alibaba快速构建Java应用
|
1月前
|
消息中间件 Java 数据库连接
Java 反射最全详解 ,框架设计必掌握!
本文详细解析Java反射机制,包括反射的概念、用途、实现原理及应用场景。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 反射最全详解 ,框架设计必掌握!
|
1月前
|
开发框架 Java 关系型数据库
Java哪个框架适合开发API接口?
在快速发展的软件开发领域,API接口连接了不同的系统和服务。Java作为成熟的编程语言,其生态系统中出现了许多API开发框架。Magic-API因其独特优势和强大功能,成为Java开发者优选的API开发框架。本文将从核心优势、实际应用价值及未来展望等方面,深入探讨Magic-API为何值得选择。
42 2
|
1月前
|
前端开发 Java 数据库连接
你不可不知道的JAVA EE 框架有哪些?
本文介绍了框架的基本概念及其在编程领域的应用,强调了软件框架作为通用、可复用的软件环境的重要性。文章分析了早期Java EE开发中使用JSP+Servlet技术的弊端,包括可维护性差和代码重用性低等问题,并阐述了使用框架的优势,如提高开发效率、增强代码规范性和可维护性及提升软件性能。最后,文中详细描述了几种主流的Java EE框架,包括Spring、Spring MVC、MyBatis、Hibernate和Struts 2,这些框架通过提供强大的功能和支持,显著提升了Java EE应用的开发效率和稳定性。
57 1
|
1月前
|
Java
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式
Java 8 引入的 Streams 功能强大,提供了一种简洁高效的处理数据集合的方式。本文介绍了 Streams 的基本概念和使用方法,包括创建 Streams、中间操作和终端操作,并通过多个案例详细解析了过滤、映射、归并、排序、分组和并行处理等操作,帮助读者更好地理解和掌握这一重要特性。
30 2
下一篇
DataWorks