Introduction to Eclipse Collections – Eclipse集合的介绍

最后修改: 2017年 8月 13日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

Eclipse Collections is another improved collection framework for Java.

Eclipse Collections是另一个用于Java的改进的集合框架。

Simply put, it provides optimized implementations as well as some additional data structures and features which are not found in the core Java.

简单地说,它提供了优化的实现以及一些额外的数据结构和功能,这些都是核心Java中所没有的。

The library provides both mutable and immutable implementations of all data structures.

该库为所有数据结构提供了可变和不可变的实现。

2. Maven Dependency

2.Maven的依赖性

Let’s start by adding the following Maven dependency to our pom.xml:

让我们先在pom.xml中加入以下Maven依赖项。

<dependency
    <groupId>org.eclipse.collections</groupId>
    <artifactId>eclipse-collections</artifactId>
    <version>8.2.0</version>
</dependency>

We can find the latest version of the library in the Maven Central Repository.

我们可以在Maven Central Repository中找到该库的最新版本。

3. The Big Picture

3.大局观

3.1. Basic Collection Types

3.1.基本集合类型

Basic collection types in Eclipse Collections are:

Eclipse集合中的基本集合类型有:。

  • ListIterable – an ordered collection that maintains insertion order and allows duplicate elements. Subinterfaces include: MutableList, FixedSizeList and ImmutableList. The most common ListIterable implementation is FastList, which is a subclass of MutableList
  • SetIterable – a collection that allows no duplicate elements. It can be sorted or unsorted. Subinterfaces include: SortedSetIterable and UnsortedSetIterable. The most common unsorted SetIterable implementation is UnifiedSet
  • MapIterable – a collection of key/value pairs. Subinterfaces include MutableMap, FixedSizeMap and ImmutableMap. Two common implementations are UnifiedMap and MutableSortedMap. While UnifiedMap does not maintain any order, MutableSortedMap maintains the natural order of elements
  • BiMap – a collection of key/value pairs that can be iterated through in either direction. BiMap extends the MapIterable interface
  • Bag – an unordered collection that allows duplicates. Subinterfaces include MutableBag and FixedSizeBag. The most common implementation is HashBag
  • StackIterable – a collection that maintains “last-in, first-out” order, iterating through elements in reverse insertion order. Subinterfaces include MutableStack and ImmutableStack
  • MultiMap – a collection of key/value pairs that allows multiple values for each key

3.2. Primitive Collections

3.2.原始集合

The framework also provides a huge set of primitive collections; their implementations are named after the type they hold. There are mutable, immutable, synchronized and unmodifiable forms for each type of them:

该框架还提供了一个庞大的原始集合;它们的实现是以它们持有的类型命名的。每种类型的集合都有可变的、不可变的、同步的和不可修改的形式。

  • Primitive Lists
  • Primitive Sets
  • Primitive Stacks
  • Primitive Bags
  • Primitive Maps
  • IntInterval

There is a huge number of primitive map forms covering all possible combinations of either primitive or object keys and either primitive or object values.

有大量的基元图形式,涵盖了基元或对象键和基元或对象值的所有可能组合。

A quick note – an IntInterval is a range of integers that may be iterated over using a step value.

简单说明一下–Interval是一个整数范围,可以用一个步长值进行迭代。

4. Instantiating a Collection

4.实例化一个集合

To add elements to an ArrayList or HashSet, we instantiate a collection by calling the no-arg constructor and then adding each element one by one.

为了向ArrayListHashSet添加元素,我们通过调用无参数构造函数来实例化一个集合,然后逐一添加每个元素。

While we can still do that in Eclipse Collections, we can also instantiate a collection and provide all initial elements at the same time in a single line.

虽然我们仍然可以在Eclipse Collections中这样做,但我们也可以在一行中同时实例化一个集合并提供所有初始元素。

Let’s see how we can instantiate a FastList:

让我们看看如何实例化一个FastList

MutableList<String> list = FastList.newListWith(
  "Porsche", "Volkswagen", "Toyota", "Mercedes", "Toyota");

Similarly, we can instantiate a UnifiedSet and add elements to it by passing the elements to the newSetWith() static method:

同样地,我们可以实例化一个UnifiedSet,并通过将元素传递给newSetWith()静态方法来向其添加元素。

Set<String> comparison = UnifiedSet.newSetWith(
  "Porsche", "Volkswagen", "Toyota", "Mercedes");

Here’s how we can instantiate a HashBag:

下面是我们如何实例化一个HashBag

MutableBag<String> bag = HashBag.newBagWith(
  "Porsche", "Volkswagen", "Toyota", "Porsche", "Mercedes");

Instantiating maps and adding key and value pairs to them is similar. The only difference is that we pass the key and value pairs to the newMapWith() method as implementations of the Pair interface.

实例化地图并向其添加键和值对是类似的。唯一的区别是,我们将键和值对作为Pair接口的实现传递给newMapWith()方法。

Let’s take UnifiedMap as an example:

让我们以UnifiedMap为例。

Pair<Integer, String> pair1 = Tuples.pair(1, "One");
Pair<Integer, String> pair2 = Tuples.pair(2, "Two");
Pair<Integer, String> pair3 = Tuples.pair(3, "Three");

UnifiedMap<Integer, String> map = new UnifiedMap<>(pair1, pair2, pair3);

We can still use the Java Collections API approach:

我们仍然可以使用Java集合API的方法。

UnifiedMap<Integer, String> map = new UnifiedMap<>();

map.put(1, "one");
map.put(2, "two");
map.put(3, "three");

Since immutable collections cannot be modified, they do not have implementations of methods that modify collections such as add() and remove().

由于不可变的集合不能被修改,它们没有修改集合的方法的实现,如add()remove()

Unmodifiable collections, however, allow us to call these methods but will throw an UnsupportedOperationException if we do.

然而,不可修改的集合允许我们调用这些方法,但如果我们这样做,将抛出一个不支持操作的异常

5. Retrieving Elements from Collections

5.从集合中检索元素

Just like using standard Lists, elements of Eclipse Collections Lists can be retrieved by their index:

就像使用标准的 Lists 一样,Eclipse Collections Lists 的元素可以通过其索引来检索。

list.get(0);

And values of Eclipse Collections maps can be retrieved using their key:

而Eclipse集合图的值可以用它们的键来检索。

map.get(0);

The getFirst() and getLast() methods can be used to retrieve first and last elements of a list respectively. In the case of other collections, they return the first and the last element that would be returned by an iterator.

getFirst()getLast()方法可分别用于检索列表的第一个和最后一个元素。在其他集合的情况下,它们会返回由迭代器返回的第一个和最后一个元素。

map.getFirst();
map.getLast();

The methods max() and min() can be used to get the maximum and minimum values of a collection based on the natural ordering.

方法max()min()可以用来根据自然排序获得一个集合的最大和最小值。

map.max();
map.min();

6. Iterating Over a Collection

6.在一个集合上迭代

Eclipse Collections provides many ways for iterating over collections. Let’s see what they are and how they work in practice.

Eclipse Collections 提供了许多对集合进行迭代的方法。让我们看看它们是什么,以及它们在实践中是如何工作的。

6.1. Collection Filtering

6.1.收集过滤

The select pattern returns a new collection containing elements of a collection that satisfy a logical condition. It is essentially a filtering operation.

选择模式返回一个新的集合,其中包含满足逻辑条件的集合的元素。它本质上是一个过滤操作。

Here’s an example:

这里有一个例子。

@Test
public void givenListwhenSelect_thenCorrect() {
    MutableList<Integer> greaterThanThirty = list
      .select(Predicates.greaterThan(30))
      .sortThis();
    
    Assertions.assertThat(greaterThanThirty)
      .containsExactly(31, 38, 41);
}

The same thing can be done using a simple lambda expression:

同样的事情也可以用一个简单的lambda表达式来完成。

return list.select(i -> i > 30)
  .sortThis();

The reject pattern is the opposite. It returns a collection of all the elements that do not satisfy a logical condition.

拒绝模式正好相反。它返回一个不满足逻辑条件的所有元素的集合。

Let’s see an example:

让我们看一个例子。

@Test
public void whenReject_thenCorrect() {
    MutableList<Integer> notGreaterThanThirty = list
      .reject(Predicates.greaterThan(30))
      .sortThis();
    
    Assertions.assertThat(notGreaterThanThirty)
      .containsExactlyElementsOf(this.expectedList);
}

Here, we reject all elements that are greater than 30.

这里,我们拒绝所有大于30的元素。

6.2. The collect() Method

6.2.collect()方法

The collect method returns a new collection whose elements are the results returned by the provided lambda expression – essentially it’s a combination of the map() and collect() from Stream API.

collect方法返回一个新的集合,其元素是由所提供的lambda表达式返回的结果–本质上它是Stream API中的map()collect()的结合。

Let’s see it in action:

让我们看看它的行动。

@Test
public void whenCollect_thenCorrect() {
    Student student1 = new Student("John", "Hopkins");
    Student student2 = new Student("George", "Adams");
    
    MutableList<Student> students = FastList
      .newListWith(student1, student2);
    
    MutableList<String> lastNames = students
      .collect(Student::getLastName);
    
    Assertions.assertThat(lastNames)
      .containsExactly("Hopkins", "Adams");
}

The created collection lastNames contains the last names which are collected from the students list.

创建的集合lastNames包含从students列表中收集的姓氏。

But, what if the returned collection is a collection of collections and we do not want to maintain a nested structure?

但是,如果返回的集合是一个集合的集合,而我们不想维持一个嵌套结构,怎么办?

For example, if each student has multiple addresses, and we need a collection that contains the addresses as Strings rather than a collection of collections, we can use the flatCollect() method.

例如,如果每个学生有多个地址,而我们需要一个包含地址的字符串集合,而不是一个集合的集合,我们可以使用flatCollect()方法。

Here’s an example:

这里有一个例子。

@Test
public void whenFlatCollect_thenCorrect() {
    MutableList<String> addresses = students
      .flatCollect(Student::getAddresses);
    
    Assertions.assertThat(addresses)
      .containsExactlyElementsOf(this.expectedAddresses);
}

6.3. Element Detection

6.3.元素检测

The detect method finds and returns the first element that satisfies a logical condition.

detect方法找到并返回第一个满足逻辑条件的元素。

Let’s go over a quick example:

我们来看看一个简单的例子。

@Test
public void whenDetect_thenCorrect() {
    Integer result = list.detect(Predicates.greaterThan(30));
    
    Assertions.assertThat(result)
      .isEqualTo(41);
}

The anySatisfy method determines whether any element of a collection satisfies a logical condition.

anySatisfy方法确定一个集合中的任何元素是否满足一个逻辑条件。

Here’s an example:

这里有一个例子。

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    boolean result = list.anySatisfy(Predicates.greaterThan(30));
    
    assertTrue(result);
}

Similarly, the allSatisfy method determines whether all elements of a collection satisfy a logical condition.

类似地,allSatisfy方法确定一个集合的所有元素是否满足一个逻辑条件。

Let’s see a quick example:

让我们看一个快速的例子。

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    boolean result = list.allSatisfy(Predicates.greaterThan(0));
    
    assertTrue(result);
}

6.4. The partition() Method

6.4.partition()方法

The partition method allocates each element of a collection into one of two collections depending on whether or not the element satisfies a logical condition.

partition方法将一个集合的每个元素分配到两个集合中的一个,这取决于该元素是否满足一个逻辑条件。

Let’s see an example:

让我们看一个例子。

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    MutableList<Integer> numbers = list;
    PartitionMutableList<Integer> partitionedFolks = numbers
      .partition(i -> i > 30);
	
    MutableList<Integer> greaterThanThirty = partitionedFolks
      .getSelected()
      .sortThis();
    MutableList<Integer> smallerThanThirty = partitionedFolks
      .getRejected()
      .sortThis();
    
    Assertions.assertThat(smallerThanThirty)
      .containsExactly(1, 5, 8, 17, 23);
    Assertions.assertThat(greaterThanThirty)
      .containsExactly(31, 38, 41);
}

6.5. Lazy Iteration

6.5.懒惰迭代

Lazy iteration is an optimization pattern in which an iteration method is invoked, but its actual execution is deferred until its action or return values are required by another subsequent method.

懒惰迭代是一种优化模式,其中一个迭代方法被调用,但其实际执行被推迟到另一个后续方法需要其动作或返回值时。

@Test
public void whenLazyIteration_thenCorrect() {
    Student student1 = new Student("John", "Hopkins");
    Student student2 = new Student("George", "Adams");
    Student student3 = new Student("Jennifer", "Rodriguez");

    MutableList<Student> students = Lists.mutable
      .with(student1, student2, student3);
    LazyIterable<Student> lazyStudents = students.asLazy();
    LazyIterable<String> lastNames = lazyStudents
      .collect(Student::getLastName);
    
    Assertions.assertThat(lastNames)
      .containsAll(Lists.mutable.with("Hopkins", "Adams", "Rodriguez"));
}

Here, the lazyStudents object does not retrieve the elements of the students list until the collect() method is called.

这里,lazyStudents对象在调用collect()方法之前,不会检索students列表中的元素。

7. Pairing Collection Elements

7.搭配收藏元素

The method zip() returns a new collection by combining elements of two collections into pairs. If any of the two collections is longer, the remaining elements will be truncated.

方法zip()通过将两个集合的元素合并成对,返回一个新的集合。如果两个集合中的任何一个更长,剩余的元素将被截断。

Let’s see how we can use it:

让我们看看我们如何使用它。

@Test
public void whenZip_thenCorrect() {
    MutableList<String> numbers = Lists.mutable
      .with("1", "2", "3", "Ignored");
    MutableList<String> cars = Lists.mutable
      .with("Porsche", "Volvo", "Toyota");
    MutableList<Pair<String, String>> pairs = numbers.zip(cars);
    
    Assertions.assertThat(pairs)
      .containsExactlyElementsOf(this.expectedPairs);
}

We can also pair a collection’s elements with their indexes using the zipWithIndex() method:

我们还可以使用zipWithIndex()方法将一个集合的元素与它们的索引配对。

@Test
public void whenZip_thenCorrect() {
    MutableList<String> cars = FastList
      .newListWith("Porsche", "Volvo", "Toyota");
    MutableList<Pair<String, Integer>> pairs = cars.zipWithIndex();
    
    Assertions.assertThat(pairs)
      .containsExactlyElementsOf(this.expectedPairs);
}

8. Converting Collections

8.转换收藏品

Eclipse Collections provides simple methods for converting a container type to another. These methods are toList(), toSet(), toBag() and toMap().

Eclipse Collections 提供了将一个容器类型转换为另一个容器类型的简单方法。这些方法是toList()toSet()toBag()toMap()

Let’s see how we can use them:

让我们看看我们如何使用它们。

public static List convertToList() {
    UnifiedSet<String> cars = new UnifiedSet<>();
    
    cars.add("Toyota");
    cars.add("Mercedes");
    cars.add("Volkswagen");
    
    return cars.toList();
}

Let’s run our test:

让我们运行我们的测试。

@Test
public void whenConvertContainerToAnother_thenCorrect() {
    MutableList<String> cars = (MutableList) ConvertContainerToAnother 
      .convertToList();
    
    Assertions.assertThat(cars)
      .containsExactlyElementsOf(
      FastList.newListWith("Volkswagen", "Toyota", "Mercedes"));
}

9. Conclusion

9.结论

In this tutorial, we’ve seen a quick overview of Eclipse Collections and the features they provide.

在本教程中,我们已经看到了Eclipse集合的快速概述以及它们提供的功能。

The full implementation of this tutorial is available over on GitHub.

本教程的完整实现可在GitHub上获得