首页 > 编程语言 >Java 集合框架1:Collection

Java 集合框架1:Collection

时间:2022-11-30 14:14:22浏览次数:47  
标签:Java 实现 Collection 接口 compareTo 集合 排序 方法

目录

集合框架

1.概述

集合 collection ,也称为 container 容器,一个将多个对象组合成一个单元的对象。集合用于存储、返回、操作以及聚合。集合框架是一个统一表示和管理集合的框架。它减少不必要的编程工作,提升程序的速度和质量、互操作性,减少重复设计。

接口、实现、聚合操作和算法共同组成了 Java 的集合框架。

  • 接口:表示集合的抽象数据类型。接口允许独立于集合具体表示(实现)来操作集合。
  • 实现:对集合接口的具体实现。
  • 算法:集合上的各种计算操作,算法应该具有多态性,即同样的方法可以在不同的实现下的集合接口下使用。

2.Collection

Collection 是集合框架最基本的接口,除了 Map 外,List、Queue、Set 类集合都实现了它。

基本方法

1.基础操作:

  • int size();
  • boolean isEmpty();
  • boolean contains(Object o);
  • boolean add(E e);
  • boolean remove(Object o);
  • Iterator<E> iterator();

2.bulk 操作有:

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

3.stream 流:

  • default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    
  • default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
    

4.针对Array,还有以下的额外操作:

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

容器遍历

遍历容器主要有三种方法: 聚合操作、for-each、迭代器Iterator。

String joined = elements.stream() 
    .map(Object::toString) 
    .collect(Collectors.joining(", "));
for (Object o : collection) 
    System.out.println(o);
public interface Iterator<E> { 
    boolean hasNext(); 
    E next(); 
    void remove(); //optional 
} 

对于 Iterator 中的 remove 方法,只能在每次 next 方法之后至多调用一次,否则将会抛出异常。使用迭代器的好处是可以对 collection 中的元素进行删除。在迭代过程中,Iterator 的 remove 方法是唯一可以删除元素的操作,如果在迭代过程中通过其他方式对元素有其他修改,将会抛出异常。

在下面的两种情况下使用 Iterator,而不是 for-each:

  • 在迭代中需要删除元素。
  • 并行的对容器进行迭代操作。
static void filter(Collection<?> c) { 
  for (Iterator<?> it = c.iterator(); it.hasNext(); ) 
    if (!cond(it.next())) 
      it.remove(); 
} 

容器实现

集合的实现实现了集合接口的方法,主要包含:

  • General-purpose,使用最广泛,在日常场景中使用。
  • Special-purpose,对于特殊场景设计,具有非标准的性能特点和使用限制,行为。
  • Concurrent,支持并发。
  • Wrapper,用于组合不同的实现,比如为 general-purpose 实现的集合添加特殊的功能。
  • Convenience,最小实现,通过静态工厂方法方法获得,用于替代 general-purpose 的方便,有效的实现。
  • Abstract,骨架实现,方便构成。

上面的实现都允许插入 null 元素;并且都不是线程安全的。具有快速失败(fast-fail)的迭代器设计:当迭代容器时检测到了并行修改时,迭代器将会立即抛出异常,防止任意的、不可期的行为发生。它们都实现了 Serializable 接口,并且都实现了 public 的 clone 方法。遗留的 Vector 和 Hashtable 是线程安全的,但已经建议不再使用了。如果需要线程安全的容器,可以使用 Collections 中的 synchronized wrapper 将上面的实现转化成线程安全的,另外在 Java 的 concurrent 包中,提供了更多高性能的并发容器,比如 BlockingQueue , ConcurrentHashMap 等。

元素排序

集合中某些实现类底层是按照一定规则进行存储,如 TreeMap 、 TreeSet。这里有两种排序方式:自然排序与定制排序。

1.自然排序

Java 提供 Comparable 接口,其中有 compareTo 方法。使用自然排序,需要容器中的元素实现 Comparable 接口中的 compareTo 方法,集合的排序根据 compareTo 方法来比较大小进行排序。

Java 基本类型的包装类都已实现 compareTo 方法。

对于 Comparable 接口的实现,最好符合以下事项:

  • 符合e1.compareTo(e2) == 0e1.equals(e2)等价。
  • 对 null 元素比较需要抛出 NullPointerException。因为 null 不是任何类的实例。
  • compareTo 返回负数、零、正数,分别表示小于、等于、大于,且满足sign(x.compareTo(y)) == -sign(y.compareTo(x))
  • compareTo 的实现满足传递性:x.compareTo(y) == 0 => sign(x.compareTo(z)) = sign(y.compareTo(z))

2.定制排序

如果需要按特殊规则排序或者元素本身不具备比较性时,需要使用定制排序。

定制排序需要一个实现 Comparator 接口的 compare 方法的实现类,并在创建接口时将其作为参数传递过去。示例如下:

public class MyComparator implements Comparator {
    @Override
    public int compare(Object o1, Object o2) {
        // 指定排序规则
        return 0;
    }
}
TreeSet tree = new TreeSet(new MyComparator());

3.Collections

collections 是作为 collection 的工具实现类。常用方法示例如下:

包装器实现(Wrapper Implementations)

collections 的包装器是装饰器模式来实现的,包装器并不提供公用类,都只提供静态的工厂方法。

1.同步包装器(Synchronization Wrappers)

同步包装器为非线程安全的 collection 提供同步,通过以下方法,返回对应实现类的同步版本类:

上面的每一个方法返回线程安全的基于指定 collection 的同步 collection。

下面以 synchronizedList 方法装饰 ArrayList 为例,使用以下方式返回线程安全的 SynchronizedRandomAccessList:

List<Type> list = Collections.synchronizedList(new ArrayList<Type>()); 

ArrayList 实现了 RandomAccess 接口,应当返回 SynchronizedRandomAccessList ,而 SynchronizedRandomAccessList 继承 SynchronizedList ,实际上的同步实现在 SynchronizedList 中。(如果装饰 LinkedList,因为未实现 RandomAccess 接口,直接返回 SynchronizedList。)

SynchronizedList 类中,所有方法内部添加了 synchronized 来同步代码块。

注意:SynchronizedList 只实现了与 ArrayList 实现的接口,对于 ArrayList 提供的额外方法,如 ensureCapacity,无法调用。其它同步包装器也如此。

2.不可变包装器(Unmodified Wrappers)

不可变包装器将 collection 进行改变的方法实现为抛出 UnsupportedOperationException,来保证 collection 不可变或只读,通过以下方法,返回对应实现类的不可变版本类:

Unmodified Wrappers 的实现方式与 Synchronization Wrappers 实现类似,都采用了装饰器模式。以返回的 UnmodifiableList 为例,对于原本修改的方法,“重写”为抛出异常:

Empty 对象

Collections 以下方法返回空的容器:

它主要用于取代 null 的情况,当某个方法需要一个容器作为参数且不能为 null,你不想提供任何值的时候,就创建一个空的 collection:

tourist.declarePurchases(Collections.emptySet()); 

其实现方式是返回对应的 Empty 对象,以 emptyList 为例:

可以看出,每次调用 emptyList 时,返回的都是同一个 EmptyList 对象,以达到共用的目的

不可变单例 Set(Immutable Singleton Set)

singleton 用于创建只包含单个指定元素的 Set。常用的就是移除集合中某个元素:

c.removeAll(Collections.singleton(e));

另外一个类似的就是移除 Map 中指定的 value:

job.values().removeAll(Collections.singleton(LAWYER)); 

不可变多副本列表(Immutable Multiple-Copy List)

nCopies 方法可以创建同个对象的多个副本的不可变 List 。比如创建具有 1000 个 Type 类型的 null 对象:

List<Type> list = new ArrayList<Type>(Collections.nCopies(1000, (Type) null);

第二个主要的用法是在List后面追加:

lovablePets.addAll(Collections.nCopies(69, "fruit bat")); 

元素排序

sort 方法实现了对 List 进行排序,其实归根到底还是调用了 Arrays 的排序算法。

Arrays 的 mergeSort 用到了快速排序算法,其比较大小的依据为 Comparable 接口中的 compareTo 方法。

所以调用 sort 方法时,需要保证集合中的元素实现了 Comparable 接口

4.Stream API

Stream 是 Java 8 中处理集合的关键抽象概念,它可以指定对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。

它具有如下特点:

  • Stream 自己不会存储元素。
  • Stream 不会改变源对象,相反,它们会返回一个持有结果的新 Stream。
  • Stream 操作是延迟执行的,这意味这它们会等到需要结果的时候才执行。

标签:Java,实现,Collection,接口,compareTo,集合,排序,方法
From: https://www.cnblogs.com/meyok/p/16938224.html

相关文章