文章目录
1.介绍
比较两个基于 Java 的开源库:Apache Commons 和 Google Guava。 这两个库都具有丰富的功能集,其中包含大量实用程序 API,主要用于集合和 I/O 领域。
2.两个类库的简史
Google Guava 是 Google 的一个项目,主要由该组织的工程师开发,尽管它现在已经开源。 启动它的主要动机是将 JDK 1.5 中引入的泛型包含到 Java 集合框架或 JCF 中,并增强其功能。
自成立以来,该库扩展了其功能,现在包括图形、函数式编程、范围对象、缓存和字符串操作。
Apache Commons 最初是作为 Jakarta 项目的一个补充核心 Java 集合 API 的项目,最终成为 Apache 软件基金会的一个项目。 多年来,它已扩展为各种其他领域的大量可重用 Java 组件,包括(但不限于)成像、I/O、密码学、缓存、网络、验证和对象池。
由于这是一个开源项目,Apache 社区的开发人员不断添加到该库以扩展其功能。 同时,非常注意保持向后兼容性。
3.Maven依赖
要包含 Guava,需要将其依赖项添加到 pom.xml 中:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>
对于 Apache Commons,它有点不同。 根据要使用的实用程序,必须添加那个特定的实用程序。 例如,对于集合,需要添加:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.4</version>
</dependency>
4.双向Map
可以通过键和值访问的映射称为双向映射。 JCF 没有这个功能。
在这两种情况下,我们都会以一周中的几天为例来获取给定日期的日期名称,反之亦然。
4.1. Guava’s BiMap
Guava 提供了一个接口——BiMap,作为一个双向映射。 它可以使用其实现 EnumBiMap、EnumHashBiMap、HashBiMap 或 ImmutableBiMap 之一进行实例化。
双映射(或“双向映射”)是一种保留其值及其键的唯一性的映射。 此约束使 bimap 能够支持“反向视图”,这是另一个 bimap,包含与此 bimap 相同的条目,但具有相反的键和值。
@Test
public void guavaBiMapTest() {
//双向视图 如果value重复 会报
//value already present: Monday
//这里使用 HashBiMap:
BiMap<Integer, String> daysOfWeek = HashBiMap.create();
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");
BiMap<String, Integer> inverse = daysOfWeek.inverse();
System.out.println(inverse);
assertEquals(Integer.valueOf(7), inverse.get("Sunday"));
assertEquals("Tuesday", daysOfWeek.get(2));
}
4.2. Apache’s BidiMap
同样,Apache 提供了它的 BidiMap 接口:
这里使用 TreeBidiMap。,还有其他实现,例如 DualHashBidiMap 和 DualTreeBidiMap。
@Test
public void apacheBidiMapTest() {
//双向视图 如果value重复 一最后一个为准
BidiMap<Integer, String> daysOfWeek = new TreeBidiMap<>();
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");
BidiMap<String, Integer> inverseBidiMap = daysOfWeek.inverseBidiMap();
System.out.println(inverseBidiMap);
assertEquals(Integer.valueOf(7), inverseBidiMap.get("Sunday"));
assertEquals("Tuesday", daysOfWeek.get(2));
}
在一些简单的性能测试中,这种双向映射仅在插入方面落后于其对应的 Guava。 获取键和值的速度要快得多。
5.将键映射到多个值
对于希望将多个键映射到不同值的情况,例如水果和蔬菜的购物车集合,这两个库为提供了独特的解决方案。
5.1. Guava’s MultiMap
@Test
public void guavaMultiMapTest(){
Multimap<String, String> groceryCart = ArrayListMultimap.create();
groceryCart.put("Fruits", "苹果");
groceryCart.put("Fruits", "香蕉");
groceryCart.put("Fruits", "草莓");
groceryCart.put("Vegetables", "土豆");
groceryCart.put("Vegetables", "西红柿");
List<String> fruits = Arrays.asList("苹果", "香蕉", "草莓");
assertEquals(fruits, groceryCart.get("Fruits"));
List<String> veggies = Arrays.asList("土豆", "西红柿");
assertEquals(veggies, groceryCart.get("Vegetables"));
}
此外,MultiMap 能够从Map中删除给定的条目或整个值集:
@Test
public void givenMultiValuedMapRemoved() {
Multimap<String, String> groceryCart = ArrayListMultimap.create();
groceryCart.put("Fruits", "苹果");
groceryCart.put("Fruits", "香蕉");
groceryCart.put("Fruits", "草莓");
groceryCart.put("Vegetables", "土豆");
groceryCart.put("Vegetables", "西红柿");
assertEquals(5, groceryCart.size());
groceryCart.remove("Fruits", "苹果");
assertEquals(4, groceryCart.size());
groceryCart.removeAll("Fruits");
assertEquals(2, groceryCart.size());
}
5.2. Apache MultiValuedMap
MultiValuedMap无法灵活地删除单个条目,例如从 Fruits 中删除 苹果。 只能删除整个 Fruits 集:
@Test
public void apacheMultiMapTest(){
MultiValuedMap<String, String> groceryCart = new ArrayListValuedHashMap<>();
groceryCart.put("Fruits", "苹果");
groceryCart.put("Fruits", "香蕉");
groceryCart.put("Fruits", "草莓");
groceryCart.put("Vegetables", "土豆");
groceryCart.put("Vegetables", "西红柿");
List<String> fruits = Arrays.asList("苹果", "香蕉", "草莓");
assertEquals(fruits, groceryCart.get("Fruits"));
List<String> veggies = Arrays.asList("土豆", "西红柿");
assertEquals(veggies, groceryCart.get("Vegetables"));
assertEquals(5, groceryCart.size());
groceryCart.remove("Fruits");
assertEquals(2, groceryCart.size());
}
6.将多个键映射到一个值
6.1. Guava Table
@Test
public void guavaTable() {
Table<String, String, String> cityCoordinates = HashBasedTable.create();
//rowKey columnKey value
cityCoordinates.put("116.397128° N", "39.916527° W", "北京");
cityCoordinates.put("121.48941° N", "31.40527° W", "上海");
cityCoordinates.put("113.27324° N", "23.15792° W", "广州");
List<String> expectedLongitudes = Arrays.asList("39.916527° W", "31.40527° W", "23.15792° W");
assertArrayEquals(expectedLongitudes.toArray(), cityCoordinates.columnKeySet().toArray());
List<String> expectedCities = Arrays.asList("北京", "上海", "广州");
assertArrayEquals(expectedCities.toArray(), cityCoordinates.values().toArray());
assertTrue(cityCoordinates.rowKeySet().contains("116.397128° N"));
Map<String, Map<String, String>> stringMapMap = cityCoordinates.rowMap();
//{116.397128° N={39.916527° W=北京}, 121.48941° N={31.40527° W=上海}, 113.27324° N={23.15792° W=广州}}
System.out.println(stringMapMap);
Collection<Map<String, String>> values = stringMapMap.values();
//[{39.916527° W=北京}, {31.40527° W=上海}, {23.15792° W=广州}]
System.out.println(values);
HashMap<String, String> map = Maps.newHashMap();
values.forEach(map::putAll);
//{39.916527° W=北京, 31.40527° W=上海, 23.15792° W=广州}
System.out.println(map);
}
正如上面例子,可以获得行、列和值的 Set 视图。
表还为我们提供了查询其行或列的能力。
但是,表限制只能将两个键映射到一个值。 在 Guava 中,还没有将两个以上的键映射到单个值的替代方法。
6.2. Apache’s MultiKeyMap
@Test
public void apacheTable() {
MultiKeyMap<String, String> cityCoordinates = new MultiKeyMap<>();
cityCoordinates.put("116.397128° N", "39.916527° W", "北京");
cityCoordinates.put("121.48941° N", "31.40527° W", "上海");
cityCoordinates.put("113.27324° N", "23.15792° W", "广州");
List<String> latitudes = new ArrayList<>();
cityCoordinates.forEach((key, value) -> {
latitudes.add(key.getKey(0));
});
System.out.println(latitudes);
List<String> longitudes = new ArrayList<>();
cityCoordinates.forEach((key, value) -> {
longitudes.add(key.getKey(1));
});
System.out.println(longitudes);
List<String> cities = new ArrayList<>();
cityCoordinates.forEach((key, value) -> {
cities.add(value);
});
System.out.println(cities);
}
MultiKeyMap 还提供了将两个以上的键映射到一个值的可能性。 例如,它使我们能够将一周中的几天映射为工作日或周末:
7.Apache Commons Collections 与 Google Guava
Google Guava 的诞生是因为需要在库中使用泛型,而 Apache Commons 没有提供。
但是,在从集合中获取值时,Apache 在性能方面提供了优势。 就插入时间而言,Guava仍然占据主导地位。
尽管只比较了代码示例中的集合 API,但与 Guava 相比,Apache Commons 整体上提供了更大范围的功能。