拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 Apache Commons Collections与Google Guava

Apache Commons Collections与Google Guava

白鹭 - 2021-11-24 1043 0 0

1.概述

在本教程中,我们将比较两个基于Java的开源库: Apache CommonsGoogle Guava 。这两个库都具有丰富的功能集,主要在集合和I / O区域中具有许多实用程序API。

为简便起见,在这里我们仅描述集合框架中的一些最常用的方法以及代码示例。我们还将看到它们差异的摘要。

此外,我们还收集了一系列文章,以深入探究各种公用资源和Guava实用程序

2.两个开源库的简要历史

Google Guava是一个Google项目,主要由该组织的工程师开发,尽管该项目现已开源。启动它的主要动机是将JDK 1.5中引入的泛型包含到Java Collections FrameworkJCF中,并增强其功能。

自创建以来,该库已扩展了功能,现在包括图形,函数编程,范围对象,缓存和String操作。

Apache Commons从Jakarta项目开始,以补充核心Java集合API,并最终成为Apache Software Foundation的项目。多年来,它已扩展为其他各个领域中可重复使用的Java组件的巨大组成部分,包括(但不限于)映像,I / O,加密,缓存,联网,验证和对像池。

由于这是一个开源项目,因此来自Apache社区的开发人员不断添加该库以扩展其功能。但是,他们非常注意保持向后兼容性

3. Maven依赖

要包括番石榴,我们需要将其依赖项添加到我们的pom.xml

<dependency>

 <groupId>com.google.guava</groupId>

 <artifactId>guava</artifactId>

 <version>29.0-jre</version>

 </dependency>

它的最新版本信息可以在Maven上找到。

对于Apache Commons,情况有所不同。根据我们要使用的实用程序,我们必须添加该特定程序。例如,对于集合,我们需要添加:

<dependency>

 <groupId>org.apache.commons</groupId>

 <artifactId>commons-collections4</artifactId>

 <version>4.4</version>

 </dependency>

在我们的代码示例中,我们将使用commons-collections4

让我们立即进入有趣的部分!

4.双向Map

可以通过其键访问的映射以及值称为双向映射。 JCF没有此功能。

让我们看看我们的两种技术如何为他们提供的。在这两种情况下,我们都将以一周中的某几天为例,以给出其日期的日期作为名称,反之亦然。

4.1。番石榴的BiMap

Guava提供了一个接口BiMap ,作为双向地图。 EnumBiMapEnumHashBiMapHashBiMapImmutableBiMap之一来实例化它

在这里,我们使用HashBiMap

BiMap<Integer, String> daysOfWeek = HashBiMap.create();

填充它类似于Java中的任何映射:

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");

以下是一些JUnit测试来证明这一概念:

@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 Apache的BidiMap

同样,Apache为我们提供了其BidiMap接口:

BidiMap<Integer, String> daysOfWeek = new TreeBidiMap<Integer, String>();

在这里,我们使用TreeBidiMap 。但是,还有其他实现,例如DualHashBidiMapDualTreeBidiMap

要填充它,我们可以像上面BiMap

它的用法也非常相似:

@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));

 }

在一些简单的性能测试中, 此双向映射仅在插入时落后于其Guava副本。它在获取键和值时要快得多

5.将键映射到多个值

对于需要将多个键映射到不同值的用例,例如水果和蔬菜的杂货车集合,这两个库为我们提供了独特的解决方案。

5.1 Guava的MultiMap

首先,让我们看看如何实例化和初始化MultiMap

Multimap<String, String> groceryCart = ArrayListMultimap.create();



 groceryCart.put("Fruits", "Apple");

 groceryCart.put("Fruits", "Grapes");

 groceryCart.put("Fruits", "Strawberries");

 groceryCart.put("Vegetables", "Spinach");

 groceryCart.put("Vegetables", "Cabbage");

然后,我们将使用几个JUnit测试来观察它的运行情况:

@Test

 public void givenMultiValuedMap_whenFruitsFetched_thenFruitsReturned() {

 List<String> fruits = Arrays.asList("Apple", "Grapes", "Strawberries");

 assertEquals(fruits, groceryCart.get("Fruits"));

 }



 @Test

 public void givenMultiValuedMap_whenVeggiesFetched_thenVeggiesReturned() {

 List<String> veggies = Arrays.asList("Spinach", "Cabbage");

 assertEquals(veggies, groceryCart.get("Vegetables"));

 }

此外, MultiMap使我们能够从地图中删除给定的条目或整个值集

@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());

 }

如我们所见,在这里,我们首先从“ Fruits Apple ,然后删除了整个“ Fruits集中。

5.2。 Apache的MultiValuedMap

再次,让我们从实例化MultiValuedMap开始:

MultiValuedMap<String, String> groceryCart = new ArrayListValuedHashMap<>();

由于填充它与上一节中看到的相同,因此让我们快速查看一下用法:

@Test

 public void givenMultiValuedMap_whenFruitsFetched_thenFruitsReturned() {

 List<String> fruits = Arrays.asList("Apple", "Grapes", "Strawberries");

 assertEquals(fruits, groceryCart.get("Fruits"));

 }



 @Test

 public void givenMultiValuedMap_whenVeggiesFetched_thenVeggiesReturned() {

 List<String> veggies = Arrays.asList("Spinach", "Cabbage");

 assertEquals(veggies, groceryCart.get("Vegetables"));

 }

可以看到,它的用法也一样!

但是,在这种情况下,我们没有灵活性来删除单个条目,例如从Fruits. Apple我们只能删除整个**Fruits** :

@Test

 public void givenMultiValuedMap_whenFuitsRemoved_thenVeggiesPreserved() {

 assertEquals(5, groceryCart.size());



 groceryCart.remove("Fruits");

 assertEquals(2, groceryCart.size());

 }

6.将多个键映射到一个值

在这里,我们将以经度和纬度为例,分别映射到各个城市:

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");

现在,我们将看到如何实现这一目标。

6.1。Guava的Table

Guava提供的Table可以满足上述用例:

Table<String, String, String> cityCoordinates = HashBasedTable.create();

这是我们可以从中得出的一些用法:

@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"));

 }

如我们所见,我们可以获得行,列和值Set

Table还为我们提供了查询其行或列的能力

让我们考虑一个电影桌来演示这一点:

Table<String, String, String> 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");

以下是一些我们可以在movies Table不言自明的示例搜索:

@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"));

 }

但是, Table限制了我们仅将两个键映射到一个值。在Guava中,我们还没有其他选择可以将两个以上的键映射到一个值。

6.2。 Apache的MultiKeyMap

回到我们的cityCoordinates示例,这是我们如何使用MultiKeyMap操作它的方法:

@Test

 public void givenCoordinatesMultiKeyMap_whenQueried_thenOK() {

 MultiKeyMap<String, String> cityCoordinates = new MultiKeyMap<String, String>();



 // 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());

 }

从上面的代码片段可以看出,要得出与Guava的Table相同的断言,我们必须遍历MultiKeyMap

但是, MultiKeyMap还提供了将两个以上的键映射到一个值的可能性。例如,它使我们能够将星期几映射为工作日或周末:

@Test

 public void givenDaysMultiKeyMap_whenFetched_thenOK() {

 days = new MultiKeyMap<String, String>();

 days.put("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Weekday");

 days.put("Saturday", "Sunday", "Weekend");



 assertFalse(days.get("Saturday", "Sunday").equals("Weekday"));

 }

7. Apache Commons Collections与Google Guava的比较

根据其工程师的说法, Google Guava诞生于使用该库中的泛型的需要,而Apache Commons不提供该泛型。它也遵循对T恤的collection API要求。另一个主要优点是它正在积极开发中,并且经常发布新版本。

但是,在从集合中获取值的同时,Apache在性能方面具有优势。不过,就插入时间而言,番石榴仍然占据了蛋糕的位置。

尽管我们仅比较了代码示例中的collection API,但与Guava相比,Apache Commons整体上提供了更多的功能

8.结论

在本教程中,我们比较了Apache Commons和Google Guava提供的某些功能,特别是在集合框架方面。

在这里,我们只是简单介绍了两个库必须提供的内容。

而且,这不是“或非”比较。正如我们的代码示例所演示的,这两者都有各自独有的功能,并且在某些情况下两者可以共存

标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *