Mencari Elemen dalam Koleksi di Groovy

1. Pengenalan

Groovy menyediakan sebilangan besar kaedah untuk meningkatkan keupayaan teras Java.

Dalam tutorial ini, kami akan menunjukkan bagaimana Groovy melakukan ini ketika memeriksa elemen dan menjumpainya dalam beberapa jenis koleksi.

2. Uji Sekiranya Elemen Terdapat

Pertama, kita akan menumpukan pada pengujian hanya jika koleksi tertentu mengandungi elemen.

2.1. Senaraikan

Java sendiri menyediakan beberapa cara untuk memeriksa item dalam senarai dengan java.util. Daftar :

  • Yang mengandungi kaedah
  • The indexOf kaedah

Oleh kerana Groovy adalah bahasa yang serasi dengan Java, kita dapat menggunakannya dengan selamat.

Mari kita lihat contohnya:

@Test void whenListContainsElement_thenCheckReturnsTrue() { def list = ['a', 'b', 'c'] assertTrue(list.indexOf('a') > -1) assertTrue(list.contains('a')) }

Selain itu, Groovy memperkenalkan pengendali keahlian:

element in list

Ini adalah salah satu daripada banyak pengusaha gula sintaksis yang disediakan oleh Groovy. Dengan bantuannya, kami dapat mempermudah kod kami:

@Test void whenListContainsElement_thenCheckWithMembershipOperatorReturnsTrue() { def list = ['a', 'b', 'c'] assertTrue('a' in list) }

2.2. Tetapkan

Seperti contoh sebelumnya, kita boleh menggunakan kaedah java.util.Set # berisi dan operator di :

@Test void whenSetContainsElement_thenCheckReturnsTrue() { def set = ['a', 'b', 'c'] as Set assertTrue(set.contains('a')) assertTrue('a' in set) }

2.3. Peta

Sekiranya Peta , kita dapat memeriksa sama ada kunci atau nilai secara langsung:

@Test void whenMapContainsKeyElement_thenCheckReturnsTrue() { def map = [a: 'd', b: 'e', c: 'f'] assertTrue(map.containsKey('a')) assertFalse(map.containsKey('e')) assertTrue(map.containsValue('e')) }

Atau gunakan operator keahlian untuk mencari kunci yang sepadan:

@Test void whenMapContainsKeyElement_thenCheckByMembershipReturnsTrue() { def map = [a: 'd', b: 'e', c: 'f'] assertTrue('a' in map) assertFalse('f' in map) }

Apabila digunakan dengan peta, kita harus menggunakan operator keahlian dengan berhati-hati kerana operator ini agak membingungkan untuk digunakan dengan nilai boolean. Daripada menguji keberadaan kunci, mekanisme yang mendasari mengambil nilai yang sesuai dari peta dan hanya memasukkannya ke boolean:

@Test void whenMapContainsFalseBooleanValues_thenCheckReturnsFalse() { def map = [a: true, b: false, c: null] assertTrue(map.containsKey('b')) assertTrue('a' in map) assertFalse('b' in map) assertFalse('c' in map) }

Seperti yang kita lihat dalam contoh di atas, agak berbahaya untuk digunakan dengan nilai nol sama ada untuk alasan yang sama. Groovy membuang palsu dan batal ke boolean false .

3. Semua Perlawanan dan Sebarang Pertandingan

Dalam kebanyakan kes, kami menangani koleksi yang terdiri daripada objek yang lebih kompleks. Di bahagian ini, kami akan menunjukkan bagaimana untuk memeriksa sama ada koleksi yang diberikan mengandungi sekurang-kurangnya satu elemen yang sepadan atau jika semua elemen sesuai dengan predikat tertentu.

Mari kita mulakan dengan menentukan kelas sederhana yang akan kita gunakan sepanjang contoh kita:

class Person { private String firstname private String lastname private Integer age // constructor, getters and setters }

3.1. Senarai / Set

Kali ini, kami akan menggunakan senarai objek Orang yang mudah :

private final personList = [ new Person("Regina", "Fitzpatrick", 25), new Person("Abagail", "Ballard", 26), new Person("Lucian", "Walter", 30), ]

As we mentioned before, Groovy is a Java-compatible language, so let's first create an example using the Stream API introduced by Java 8:

@Test void givenListOfPerson_whenUsingStreamMatching_thenShouldEvaluateList() { assertTrue(personList.stream().anyMatch {it.age > 20}) assertFalse(personList.stream().allMatch {it.age < 30}) }

We can also use the Groovy methods DefaultGroovyMethods#any and DefaultGroovyMethods#every that perform the check directly on the collection:

@Test void givenListOfPerson_whenUsingCollectionMatching_thenShouldEvaluateList() { assertTrue(personList.any {it.age > 20}) assertFalse(personList.every {it.age < 30}) }

3.2. Map

Let's start by defining a Map of Person objects mapped by Person#firstname:

private final personMap = [ Regina : new Person("Regina", "Fitzpatrick", 25), Abagail: new Person("Abagail", "Ballard", 26), Lucian : new Person("Lucian", "Walter", 30) ]

We can evaluate it by either its keys, values, or by whole entries. Again, let's first use the Stream API:

@Test void givenMapOfPerson_whenUsingStreamMatching_thenShouldEvaluateMap() { assertTrue(personMap.keySet().stream().anyMatch {it == "Regina"}) assertFalse(personMap.keySet().stream().allMatch {it == "Albert"}) assertFalse(personMap.values().stream().allMatch {it.age < 30}) assertTrue(personMap.entrySet().stream().anyMatch {it.key == "Abagail" && it.value.lastname == "Ballard"}) }

And then, the Groovy Collection API:

@Test void givenMapOfPerson_whenUsingCollectionMatching_thenShouldEvaluateMap() { assertTrue(personMap.keySet().any {it == "Regina"}) assertFalse(personMap.keySet().every {it == "Albert"}) assertFalse(personMap.values().every {it.age  firstname == "Abagail" && person.lastname == "Ballard"}) }

As we can see, Groovy not only adequately replaces the Stream API when manipulating maps but also allows us to perform a check directly on the Map object instead of using the java.util.Map#entrySet method.

4. Find One or More Elements in a Collection

4.1. List/Set

We can also extract elements using predicates. Let's start with the familiar Stream API approach:

@Test void givenListOfPerson_whenUsingStreamFind_thenShouldReturnMatchingElements() { assertTrue(personList.stream().filter {it.age > 20}.findAny().isPresent()) assertFalse(personList.stream().filter {it.age > 30}.findAny().isPresent()) assertTrue(personList.stream().filter {it.age > 20}.findAll().size() == 3) assertTrue(personList.stream().filter {it.age > 30}.findAll().isEmpty()) }

As we can see, the above example uses java.util.Optional for finding a single element as the Stream API forces that approach.

On the other hand, Groovy offers a much more compact syntax:

@Test void givenListOfPerson_whenUsingCollectionFind_thenShouldReturnMatchingElements() { assertNotNull(personList.find {it.age > 20}) assertNull(personList.find {it.age > 30}) assertTrue(personList.findAll {it.age > 20}.size() == 3) assertTrue(personList.findAll {it.age > 30}.isEmpty()) }

By using Groovy's API, we can skip creating a Stream and filtering it.

4.2. Map

In the case of a Map, there are several options to choose from. We can find elements amongst keys, values or complete entries. As the first two are basically a List or a Set, in this section we'll only show an example of finding entries.

Let's reuse our personMap from earlier:

@Test void givenMapOfPerson_whenUsingStreamFind_thenShouldReturnElements() { assertTrue( personMap.entrySet().stream() .filter {it.key == "Abagail" && it.value.lastname == "Ballard"} .findAny().isPresent()) assertTrue( personMap.entrySet().stream() .filter {it.value.age > 20} .findAll().size() == 3) }

And again, the simplified Groovy solution:

@Test void givenMapOfPerson_whenUsingCollectionFind_thenShouldReturnElements() { assertNotNull(personMap.find {it.key == "Abagail" && it.value.lastname == "Ballard"}) assertTrue(personMap.findAll {it.value.age > 20}.size() == 3) }

In this case, the benefits are even more significant. We skip the java.util.Map#entrySet method and use a closure with a function provided on the Map.

5. Conclusion

In this article, we presented how Groovy simplifies checking for elements and finding them in several types of collections.

Seperti biasa, contoh kod lengkap yang digunakan dalam tutorial ini terdapat di GitHub.