Apache Commons Collections 与 Google Guava

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 整体上提供了更大范围的功能。
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值