Lists in Groovy – Groovy中的列表

最后修改: 2019年 3月 6日

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

1. Overview

1.概述

In Groovy, we can work with lists just like we do in Java. But, with its support for extension methods, it ships with quite a bit more.

Groovy中,我们可以像在Java中那样处理列表。但是,由于它对扩展方法的支持,它可以提供更多的东西。

In this tutorial, we’ll look at Groovy’s take on mutating, filtering and sorting lists.

在本教程中,我们将看看Groovy对列表的突变、过滤和排序的处理。

2. Creating Groovy Lists

2.创建Groovy列表

Groovy provides certain interesting shortcuts when working with collections, which makes use of its support for dynamic typing and literal syntax.

Groovy在处理集合时提供了某些有趣的快捷方式,这利用了它对动态类型和字面语法的支持。

Let’s begin by creating a list with some values using the shorthand syntax:

让我们先用速记语法创建一个带有一些数值的列表。

def list = [1,2,3]

Similarly, we can create an empty list:

同样地,我们可以创建一个空列表。

def emptyList = []

By default, Groovy creates an instance of java.util.ArrayList.

默认情况下,Groovy会创建一个java.util.ArrayList的实例。

However, we can also specify the type of list to create:

然而,我们也可以指定要创建的列表的类型

def linkedList = [1,2,3] as LinkedList
ArrayList arrList = [1,2,3]

Next, lists can be used to create other lists by using a constructor argument:

接下来,列表可以通过使用构造函数参数来创建其他的列表。

def copyList = new ArrayList(arrList)

We can also do this by cloning:

我们也可以通过克隆来做到这一点。

def cloneList = arrList.clone()

Note that cloning creates a shallow copy of the list.

请注意,克隆会创建一个列表的浅层拷贝。

Groovy uses the “==” operator to compare the elements in two lists for equality.

Groovy使用”==”操作符来比较两个列表中的元素是否相等。

Continuing with the previous example, on comparing cloneList with arrlist, the result is true:

继续前面的例子,在比较cloneListarrlist时,结果是true

assertTrue(cloneList == arrList)

Now let’s look at how to perform some common operations on lists.

现在让我们来看看如何对列表进行一些常见的操作。

3. Retrieving Items From a List

3.从列表中检索项目

We can get an item from a list using the literal syntax:

我们可以使用字面语法从一个列表中获取一个项目。

def list = ["Hello", "World"]
assertTrue(list[1] == "World")

Or we can use the get() and getAt() methods:

或者我们可以使用get()getAt()方法。

assertTrue(list.get(1) == "World")
assertTrue(list.getAt(1) == "World")

We can also get items from a list using both positive and negative indices.

我们也可以用正负指数从一个列表中获取项目。

When a negative index is used, the list is read from right to left:

当使用负数索引时,列表从右向左读。

assertTrue(list[-1] == "World")
assertTrue(list.getAt(-2) == "Hello")

Note that the get() method doesn’t support negative indexes.

注意,get()方法不支持负数索引。

4. Adding Items to a List

4.将项目添加到列表中

There are multiple shorthand ways for adding items to a list.

有多种速记方法用于向列表中添加项目。

Let’s define an empty list and add a few items to it:

让我们定义一个空的列表并向其中添加一些项目。

def list = []

list << 1
list.add("Apple")
assertTrue(list == [1, "Apple"])

Next, we can also specify the index to place the item at.

接下来,我们还可以指定放置项目的索引。

Also, if the length of the list is less than the index specified, Groovy adds as many null values as the difference:

另外,如果列表的长度小于指定的索引,Groovy会添加与差值相同数量的null

list[2] = "Box"
list[4] = true
assertTrue(list == [1, "Apple", "Box", null, true])

Lastly, we can use the “+=” operator to add new items to the list.

最后,我们可以使用 “+=”操作符来向列表中添加新的项目。

Compared to the other approaches, this operator creates a new list object and assigns it to the variable list:

与其他方法相比,该操作符创建了一个新的列表对象并将其分配给变量list

def list2 = [1,2]
list += list2
list += 12        
assertTrue(list == [1, 6.0, "Apple", "Box", null, true, 1, 2, 12])

5. Updating Items in a List

5.更新列表中的项目

We can update items in a list using the literal syntax or the set() method:

我们可以使用字面语法或set()方法更新列表中的项目。

def list =[1, "Apple", 80, "App"]
list[1] = "Box"
list.set(2,90)
assertTrue(list == [1, "Box", 90,  "App"])

In this example, the items at indexes 1 and 2 are updated with new values.

在这个例子中,索引1和2的项目被更新为新的值。

6. Removing Items From a List

6.从列表中删除项目

We can remove an item at a particular index using the remove() method:

我们可以使用remove()方法删除某个特定索引的项目。

def list = [1,2,3,4,5,5,6,6,7]
list.remove(3)
assertTrue(list == [1,2,3,5,5,6,6,7])

We can also remove an element by using the removeElement() method.

我们也可以通过使用removeElement()方法删除一个元素。

This removes the first occurrence of the element from the list:

这将从列表中删除该元素的第一次出现。

list.removeElement(5)
assertTrue(list == [1,2,3,5,6,6,7])

Additionally, we can use the minus operator to remove all occurrences of an element from the list.

此外,我们可以使用minus操作符,从列表中删除一个元素的所有出现次数。

This operator, however, does not mutate the underlying list — it returns a new list:

然而,这个操作符并不改变底层列表–它返回一个新的列表。

assertTrue(list - 6 == [1,2,3,5,7])

7. Iterating on a List

7.迭代一个列表

Groovy has added new methods to the existing Java Collections API.

Groovy为现有的Java Collections API增加了新方法。

These methods simplify operations such as filtering, searching, sorting, aggregating, etc. by encapsulating the boilerplate code. They also they support a wide range of inputs including closures and output data structures.

这些方法通过封装模板代码简化了过滤、搜索、排序、聚合等操作。它们还它们支持广泛的输入,包括闭包和输出数据结构。

Let’s start by looking at the two methods for iterating over a list.

让我们先看一下在列表上迭代的两种方法。

The each() method accepts a closure and is very similar to the foreach() method in Java.

each()方法接受一个闭包,与Java中的foreach()方法非常相似。

Groovy passes an implicit parameter it that corresponds to the current element in each iteration:

Groovy传递一个隐式参数it,对应于每次迭代中的当前元素。

def list = [1,"App",3,4]
list.each {println it * 2}

The other method, eachWithIndex(), provides the current index value in addition to the current element:

另一个方法,eachWithIndex(),除了提供当前元素的索引值外,还提供当前的索引值。

list.eachWithIndex{ it, i -> println "$i : $it" }

8. Filtering

8.过滤

Filtering is another operation that is frequently performed on lists, and Groovy provides many different methods to choose from.

过滤是另一个经常在列表上进行的操作,Groovy提供了许多不同的方法供其选择。

Let’s define a list to operate on:

让我们定义一个要操作的列表。

def filterList = [2,1,3,4,5,6,76]

To find the first object that matches a condition, we can use find:

为了找到第一个符合条件的对象,我们可以使用find

assertTrue(filterList.find {it > 3} == 4)

To find all objects that match a condition, we can use findAll:

要找到所有符合条件的对象,我们可以使用findAll

assertTrue(filterList.findAll {it > 3} == [4,5,6,76])

Let’s look at another example.

让我们看看另一个例子。

Here we want a list of all elements that are numbers:

在这里,我们想要一个所有元素的列表,这些元素是数字。

assertTrue(filterList.findAll {it instanceof Number} == [2,1,3,4,5,6,76])

Alternatively, we can use the grep method to do the same thing:

另外,我们可以使用grep方法来做同样的事情。

assertTrue(filterList.grep( Number ) == [2,1,3,4,5,6,76])

The difference between grep and find methods is that grep can accept an Object or a Closure as an argument.

grepfind方法的区别在于,grep可以接受一个Object或一个Closure作为参数。

So, it allows further reducing the condition statement to the bare minimum:

因此,它允许进一步将条件声明减少到最低限度。

assertTrue(filterList.grep {it > 6} == [76])

Additionally, grep uses Object#isCase(java.lang.Object) to evaluate the condition on each element of the list.

此外,grep使用Object#isCase(java.lang.Object)来评估列表中每个元素的条件。

Sometimes, we may only be interested in the unique items in a list. There are two overloaded methods that we can use for this purpose.

有时,我们可能只对一个列表中的唯一项目感兴趣。有两个重载方法可以用于这个目的。

The unique() method optionally accepts a closure and keeps in the underlying list only elements that match the closure conditions, while discarding others.

unique()方法可以选择接受一个闭合,并在底层列表中只保留符合闭合条件的元素,而放弃其他元素。

It uses natural ordering by default to determine uniqueness:

它默认使用自然排序来确定唯一性。

def uniqueList = [1,3,3,4]
uniqueList.unique()
assertTrue(uniqueList == [1,3,4])

Alternatively, if the requirement is not to mutate the underlying list, we can use the toUnique() method:

另外,如果要求不改变底层列表,我们可以使用toUnique()方法。

assertTrue(["A", "B", "Ba", "Bat", "Cat"].toUnique {it.size()} == ["A", "Ba", "Bat"])

If we want to check that some or all items in a list satisfy a certain condition, we can use the every() and any() methods.

如果我们想检查一个列表中的某些或所有项目是否满足某个条件,我们可以使用every()any()方法。

The every() method evaluates the condition in the closure against every element in the list.

every()方法针对列表中的每个元素评估封闭中的条件。

Then it only returns true if all elements in the list satisfy the condition:

那么它只在列表中的所有元素都满足条件时返回true

def conditionList = [2,1,3,4,5,6,76]
assertFalse(conditionList.every {it < 6})

The any() method, on the other hand, returns true if any element in the list satisfies the condition:

另一方面,any()方法,如果列表中任何元素满足条件,则返回true

assertTrue(conditionList.any {it % 2 == 0})

9. Sorting

9.分拣

By default, Groovy sorts the items in a list based on their natural ordering:

默认情况下,Groovy会根据列表中的项目的自然顺序来排序。

assertTrue([1,2,1,0].sort() == [0,1,1,2])

But we can also pass a Comparator with custom sorting logic:

但是我们也可以传递一个带有自定义排序逻辑的比较器

Comparator mc = {a,b -> a == b? 0: a < b? 1 : -1}
def list = [1,2,1,0]
list.sort(mc)
assertTrue(list == [2,1,1,0])

Additionally, we can use the min() or max() methods to find the maximum or minimum value without explicitly calling sort():

此外,我们可以使用min()max()方法来查找最大值或最小值,而无需明确调用sort()

def strList = ["na", "ppp", "as"]
assertTrue(strList.max() == "ppp")
Comparator minc = {a,b -> a == b? 0: a < b? -1 : 1}
def numberList = [3, 2, 0, 7]
assertTrue(numberList.min(minc) == 0)

10. Collecting

10.收集

Sometimes, we may want to modify the items in a list and return another list with updated values.

有时,我们可能想修改一个列表中的项目并返回另一个带有更新值的列表。

We can do this using the collect() method:

我们可以使用collect()方法来做到这一点。

def list = ["Kay","Henry","Justin","Tom"]
assertTrue(list.collect{"Hi " + it} == ["Hi Kay","Hi Henry","Hi Justin","Hi Tom"])

11. Joining

11.加入

At times, we may need to join the items in a list.

有时,我们可能需要将一个列表中的项目连接起来。

To do that, we can use the join() method:

要做到这一点,我们可以使用join()方法。

assertTrue(["One","Two","Three"].join(",") == "One,Two,Three")

12. Conclusion

12.结语

In this article, we covered a few of the extensions Groovy adds to the Java Collections API.

在这篇文章中,我们介绍了Groovy对Java Collections API的一些扩展。

We started off by looking at the literal syntax and then its usage in creating, updating, removing and retrieving items in a list.

我们首先看了字面语法,然后看了它在创建、更新、删除和检索列表中的项目的用法。

Finally, we looked at Groovy’s support for iterating, filtering, searching, collecting, joining and sorting lists.

最后,我们研究了Groovy对迭代、过滤、搜索、收集、连接和排序列表的支持。

As always all the examples discussed in the article are available over on GitHub.

像往常一样,文章中讨论的所有例子都可以在GitHub上找到over