Koleksi Apache Commons vs Google Guava

1. Ikhtisar

Dalam tutorial ini, kami akan membandingkan dua pustaka open source berbasis Java: Apache Commons dan Google Guava . Kedua pustaka memiliki kumpulan fitur yang kaya dengan banyak API utilitas terutama di area koleksi dan I / O.

Untuk singkatnya, di sini kami hanya akan menjelaskan beberapa yang paling umum digunakan dari framework koleksi bersama dengan contoh kode. Kami juga akan melihat ringkasan perbedaan mereka.

Selain itu, kami memiliki kumpulan artikel untuk mendalami berbagai hal umum dan utilitas Jambu .

2. Sejarah Singkat Dua Perpustakaan

Google Guava adalah proyek Google, terutama dikembangkan oleh para insinyur organisasi, meskipun sekarang telah menjadi sumber terbuka. The motivasi utama untuk memulai itu untuk memasukkan obat generik diperkenalkan pada JDK 1.5 ke Jawa Collections Framework , atau JCF, dan meningkatkan kemampuan.

Sejak awal, pustaka telah memperluas kemampuannya dan sekarang menyertakan grafik, pemrograman fungsional, objek rentang, cache, dan manipulasi String .

Apache Commons dimulai sebagai proyek Jakarta untuk melengkapi API kumpulan Java inti dan akhirnya menjadi proyek Apache Software Foundation. Selama bertahun-tahun, ini telah berkembang menjadi repertoar yang luas dari komponen Java yang dapat digunakan kembali di berbagai area lain, termasuk (tetapi tidak terbatas pada) pencitraan, I / O, kriptografi, caching, jaringan, validasi, dan penggabungan objek.

Karena ini adalah proyek sumber terbuka, pengembang dari komunitas Apache terus menambahkan pustaka ini untuk memperluas kemampuannya. Namun, mereka sangat berhati-hati untuk menjaga kompatibilitas ke belakang .

3. Ketergantungan Maven

Untuk memasukkan Guava, kita perlu menambahkan dependensinya ke pom.xml kita :

 com.google.guava guava 29.0-jre 

Informasi versi terbaru dapat ditemukan di Maven.

Untuk Apache Commons, ini sedikit berbeda. Bergantung pada utilitas yang ingin kita gunakan, kita harus menambahkan yang khusus itu. Misalnya untuk koleksi kita perlu menambahkan:

 org.apache.commons commons-collections4 4.4 

Dalam contoh kode kami, kami akan menggunakan commons-collections4 .

Mari melompat ke bagian yang menyenangkan sekarang!

4. Peta dua arah

Peta yang dapat diakses dengan kuncinya, serta nilai, dikenal sebagai peta dua arah. JCF tidak memiliki fitur ini.

Mari kita lihat bagaimana dua teknologi kami menawarkannya. Dalam kedua kasus, kita akan mengambil contoh hari dalam seminggu untuk mendapatkan nama hari yang diberi nomornya dan sebaliknya.

4.1. BiMap Jambu Biji

Guava menawarkan antarmuka - BiMap , sebagai peta dua arah. Hal ini dapat dipakai dengan salah satu implementasi yang EnumBiMap , EnumHashBiMap , HashBiMap , atau ImmutableBiMap .

Di sini kami menggunakan HashBiMap :

BiMap daysOfWeek = HashBiMap.create();

Mengisinya mirip dengan peta apa pun di Jawa:

daysOfWeek.put(1, "Monday"); daysOfWeek.put(2, "Tuesday"); daysOfWeek.put(3, "Wednesday"); daysOfWeek.put(4, "Thursday"); daysOfWeek.put(5, "Friday"); daysOfWeek.put(6, "Saturday"); daysOfWeek.put(7, "Sunday");

Dan berikut beberapa pengujian JUnit untuk membuktikan konsep tersebut:

@Test public void givenBiMap_whenValue_thenKeyReturned() { assertEquals(Integer.valueOf(7), daysOfWeek.inverse().get("Sunday")); } @Test public void givenBiMap_whenKey_thenValueReturned() { assertEquals("Tuesday", daysOfWeek.get(2)); }

4.2. BidiMap Apache

Demikian pula, Apache memberi kita antarmuka BidiMap :

BidiMap daysOfWeek = new TreeBidiMap();

Di sini kami menggunakan TreeBidiMap . Namun, ada implementasi lain, seperti DualHashBidiMap dan DualTreeBidiMap juga .

Untuk mengisinya , kita bisa meletakkan nilai seperti yang kita lakukan untuk BiMap di atas.

Penggunaannya juga sangat mirip:

@Test public void givenBidiMap_whenValue_thenKeyReturned() { assertEquals(Integer.valueOf(7), daysOfWeek.inverseBidiMap().get("Sunday")); } @Test public void givenBidiMap_whenKey_thenValueReturned() { assertEquals("Tuesday", daysOfWeek.get(2)); }

Dalam beberapa tes kinerja sederhana, peta dua arah ini tertinggal dari rekan Jambu hanya dalam penyisipan. Jauh lebih cepat dalam mengambil kunci serta nilai .

5. Memetakan Kunci ke Beberapa Nilai

Untuk kasus penggunaan di mana kami ingin memetakan beberapa kunci ke nilai yang berbeda, seperti koleksi keranjang belanjaan buah-buahan dan sayuran, kedua perpustakaan tersebut menawarkan solusi unik.

5.1. MultiMap Jambu Biji

Pertama, mari kita lihat cara membuat instance dan menginisialisasi MultiMap :

Multimap groceryCart = ArrayListMultimap.create(); groceryCart.put("Fruits", "Apple"); groceryCart.put("Fruits", "Grapes"); groceryCart.put("Fruits", "Strawberries"); groceryCart.put("Vegetables", "Spinach"); groceryCart.put("Vegetables", "Cabbage");

Kemudian, kami akan menggunakan beberapa pengujian JUnit untuk melihatnya beraksi:

@Test public void givenMultiValuedMap_whenFruitsFetched_thenFruitsReturned() { List fruits = Arrays.asList("Apple", "Grapes", "Strawberries"); assertEquals(fruits, groceryCart.get("Fruits")); } @Test public void givenMultiValuedMap_whenVeggiesFetched_thenVeggiesReturned() { List veggies = Arrays.asList("Spinach", "Cabbage"); assertEquals(veggies, groceryCart.get("Vegetables")); } 

Additionally, MultiMap gives us the ability to remove a given entry or an entire set of values from the map:

@Test public void givenMultiValuedMap_whenFuitsRemoved_thenVeggiesPreserved() { assertEquals(5, groceryCart.size()); groceryCart.remove("Fruits", "Apple"); assertEquals(4, groceryCart.size()); groceryCart.removeAll("Fruits"); assertEquals(2, groceryCart.size()); }

As we can see, here we first removed Apple from the Fruits set and then removed the entire Fruits set.

5.2. Apache's MultiValuedMap

Again, let's begin with instantiating a MultiValuedMap:

MultiValuedMap groceryCart = new ArrayListValuedHashMap();

Since populating it is the same as we saw in the previous section, let's quickly look at the usage:

@Test public void givenMultiValuedMap_whenFruitsFetched_thenFruitsReturned() { List fruits = Arrays.asList("Apple", "Grapes", "Strawberries"); assertEquals(fruits, groceryCart.get("Fruits")); } @Test public void givenMultiValuedMap_whenVeggiesFetched_thenVeggiesReturned() { List veggies = Arrays.asList("Spinach", "Cabbage"); assertEquals(veggies, groceryCart.get("Vegetables")); }

As we can see, its usage is also the same!

However, in this case, we don't have the flexibility to remove a single entry, such as Apple from Fruits.We can only remove the entire set of Fruits:

@Test public void givenMultiValuedMap_whenFuitsRemoved_thenVeggiesPreserved() { assertEquals(5, groceryCart.size()); groceryCart.remove("Fruits"); assertEquals(2, groceryCart.size()); }

6. Map Multiple Keys to One Value

Here, we'll take an example of latitudes and longitudes to be mapped to respective cities:

cityCoordinates.put("40.7128° N", "74.0060° W", "New York"); cityCoordinates.put("48.8566° N", "2.3522° E", "Paris"); cityCoordinates.put("19.0760° N", "72.8777° E", "Mumbai");

Now, we'll see how to achieve this.

6.1. Guava's Table

Guava offers its Table that satisfies the above use case:

Table cityCoordinates = HashBasedTable.create();

And here are some usages we can derive out of it:

@Test public void givenCoordinatesTable_whenFetched_thenOK() { List expectedLongitudes = Arrays.asList("74.0060° W", "2.3522° E", "72.8777° E"); assertArrayEquals(expectedLongitudes.toArray(), cityCoordinates.columnKeySet().toArray()); List expectedCities = Arrays.asList("New York", "Paris", "Mumbai"); assertArrayEquals(expectedCities.toArray(), cityCoordinates.values().toArray()); assertTrue(cityCoordinates.rowKeySet().contains("48.8566° N")); }

As we can see, we can get a Set view of the rows, columns, and values.

Table also offers us the ability to query its rows or columns.

Let's consider a movie table to demonstrate this:

Table movies = HashBasedTable.create(); movies.put("Tom Hanks", "Meg Ryan", "You've Got Mail"); movies.put("Tom Hanks", "Catherine Zeta-Jones", "The Terminal"); movies.put("Bradley Cooper", "Lady Gaga", "A Star is Born"); movies.put("Keenu Reaves", "Sandra Bullock", "Speed"); movies.put("Tom Hanks", "Sandra Bullock", "Extremely Loud & Incredibly Close");

And here are some sample, self-explanatory searches that we can do on our moviesTable:

@Test public void givenMoviesTable_whenFetched_thenOK() { assertEquals(3, movies.row("Tom Hanks").size()); assertEquals(2, movies.column("Sandra Bullock").size()); assertEquals("A Star is Born", movies.get("Bradley Cooper", "Lady Gaga")); assertTrue(movies.containsValue("Speed")); }

However, Table limits us to map only two keys to a value. We don't have an alternative as yet in Guava to map more than two keys to a single value.

6.2. Apache's MultiKeyMap

Coming back to our cityCoordinates example, here's how we can manipulate it using MultiKeyMap:

@Test public void givenCoordinatesMultiKeyMap_whenQueried_thenOK() { MultiKeyMap cityCoordinates = new MultiKeyMap(); // populate with keys and values as shown previously List expectedLongitudes = Arrays.asList("72.8777° E", "2.3522° E", "74.0060° W"); List longitudes = new ArrayList(); cityCoordinates.forEach((key, value) -> { longitudes.add(key.getKey(1)); }); assertArrayEquals(expectedLongitudes.toArray(), longitudes.toArray()); List expectedCities = Arrays.asList("Mumbai", "Paris", "New York"); List cities = new ArrayList(); cityCoordinates.forEach((key, value) -> { cities.add(value); }); assertArrayEquals(expectedCities.toArray(), cities.toArray()); }

As we can see from the above code snippet, to arrive at the same assertions as for Guava's Table, we had to iterate over the MultiKeyMap.

However, MultiKeyMap also offers the possibility to map more than two keys to a value. For example, it gives us the ability to map days of the week as weekdays or weekends:

@Test public void givenDaysMultiKeyMap_whenFetched_thenOK() { days = new MultiKeyMap(); days.put("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Weekday"); days.put("Saturday", "Sunday", "Weekend"); assertFalse(days.get("Saturday", "Sunday").equals("Weekday")); }

7. Apache Commons Collections vs. Google Guava

As per its engineers, Google Guava was born out of the need to use generics in the library, which Apache Commons didn't offer. It also follows the collections API requirements to the tee. Another major advantage is that it's in active development with new releases coming out frequently.

However, Apache offers an edge when it comes to performance while fetching a value from a collection. Guava still takes the cake though, in terms of insertion times.

Although we compared only the collections APIs in our code samples, Apache Commons as a whole offers a much bigger gamut of features as compared to Guava.

8. Conclusion

In this tutorial, we compared some of the functionality offered by Apache Commons and Google Guava, specifically in the area of the collections framework.

Di sini, kami hanya menggores permukaan dari apa yang ditawarkan kedua perpustakaan itu.

Selain itu, ini bukan perbandingan salah satu atau. Seperti yang ditunjukkan contoh kode kami, ada fitur unik untuk masing-masing dari keduanya, dan mungkin ada situasi di mana keduanya dapat hidup berdampingan .

Seperti biasa, kode sumber tersedia di GitHub.