Guava:集合操作

简介: Guava:集合操作

Guava Collections 可以帮助你的代码更简短精炼,更重要是它增强了代码的可读性。

本文使用的Guava版本如下:

 <!--guava-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>25.1-jre</version>
        </dependency>


Immutable Collections:

不可变对象有很多优点,包括:

  • 当对象被不可信的库调用时,不可变形式是安全的;
  • 不可变对象被多个线程调用时,不存在竞态条件问题
  • 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节);
  • 不可变对象因为有固定不变,可以作为常量来安全使用。


JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式,但我们认为不够好:

  • 还在使用 Collections.unmodifiableXXX() ? Immutable Collections 这才是真正的不可修改的集合
  • 重要提示:所有Guava不可变集合的实现都不接受null值


/**
     * @Title: Immutable Collections: 真正的不可修改的集合
     * @methodName: ImmutableTest
     * @param
     * @return void
     * @Description:
     *
     * @author: 王延飞
     * @date: 2018-06-28 6:07
     */
    public static void ImmutableTest() {
        // 大家都用过 Collections.unmodifiableXXX() 来做一个不可修改的集合。
        // 例如你要构造存储常量的 Set,你可以这样来做 :
        Set<String> set = new HashSet<String>(Arrays.asList(new String[]{"RED", "GREEN"}));
        Set<String> unmodifiableSet = Collections.unmodifiableSet(set);
        System.out.println("Collections.unmodifiableXXX():"+unmodifiableSet);
        // 这看上去似乎不错,因为每次调 unmodifiableSet.add() 都会抛出一个 UnsupportedOperationException。
        // 感觉安全了?慢!如果有人在原来的 set 上 add 或者 remove 元素会怎么样?
        // 结果 unmodifiableSet 也是被 add 或者 remove 元素了。而且构造这样一个简单的 set 写了两句长的代码。
        // 下面看看 ImmutableSet 是怎么来做地更安全和简洁 :
        ImmutableSet<String> immutableSet = ImmutableSet.of("RED", "GREEN");
        System.out.println("ImmutableSet:"+immutableSet);
        // 就这样一句就够了,而且试图调 add 方法的时候,它一样会抛出 UnsupportedOperationException。
        // 重要的是代码的可读性增强了不少,非常直观地展现了代码的用意。
        // 如果像之前这个代码保护一个 set 怎么做呢?你可以 :
        ImmutableSet<String> immutableSet2 = ImmutableSet.copyOf(set);
    }


Multiset: 看看如何把重复的元素放入一个集合

可以用两种方式看待Multiset:

  • 没有元素顺序限制的ArrayList<E>
  • Map<E, Integer>,键为元素,值为计数
 /**
     * @param
     * @return void
     * @Title: Multiset: 把重复的元素放入集合
     * @methodName: MultiSetTest
     * @Description: Multiset 并没有实现 java.util.Set 接口,它更像是一个 Bag。
     * 普通的 Set 就像这样 :[car, ship, bike],
     * 而 Multiset 会是这样 : [car x 2, ship x 6, bike x 3]。
     * @author: FLY
     * @date: 2018-06-25 10:31
     */
    public static void MultiSetTest() {
        //create a multiset collection
        Multiset<String> multiset = HashMultiset.create();
        multiset.add("a");
        multiset.add("b");
        multiset.add("c");
        multiset.add("d");
        multiset.add("a");
        multiset.add("b");
        multiset.add("c");
        multiset.add("b");
        multiset.add("b");
        multiset.add("b");
        //print the occurrence of an element
        System.out.println("Occurrence of 'b' : " + multiset.count("b"));
        //print the total size of the multiset
        System.out.println("Total Size : " + multiset.size());
        //get the distinct elements of the multiset as set(去重后的元素)
        Set<String> set = multiset.elementSet();
        //display the elements of the set
        System.out.println("Set [");
        for (String s : set) {
            System.out.println(s);
        }
        System.out.println("]");
        //display all the elements of the multiset using iterator
        Iterator<String> iterator = multiset.iterator();
        System.out.println("MultiSet [");
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        System.out.println("]");
        //display the distinct elements of the multiset with their occurrence count
        System.out.println("MultiSet [");
        for (Multiset.Entry<String> entry : multiset.entrySet()) {
            System.out.println("Element: " + entry.getElement() + ", Occurrence(s): " + entry.getCount());
        }
        System.out.println("]");
        //remove extra occurrences
        multiset.remove("b", 2);
        //print the occurrence of an element
        System.out.println("Occurence of 'b' : " + multiset.count("b"));
    }


输出结果

Occurrence of 'b' : 5
Total Size : 10
Set [
a
b
c
d
]
MultiSet [
a
a
b
b
b
b
b
c
c
d
]
MultiSet [
Element: a, Occurrence(s): 2
Element: b, Occurrence(s): 5
Element: c, Occurrence(s): 2
Element: d, Occurrence(s): 1
]
Occurence of 'b' : 3


Multimaps: 一个 key 对应多个 value

  • 每个有经验的Java程序员都在某处实现过Map<K, List<V>>或Map<K, Set<V>>,并且要忍受这个结构的笨拙。例如,Map<K, Set<V>>通常用来表示非标定有向图。Guava的 Multimap可以很容易地把一个键映射到多个值。换句话说,Multimap是把键映射到任意多个值的一般方式。
/**
     * @param
     * @return void
     * @Title: Multimap: 在 Map 的 value 里面放多个元素
     * @methodName: MultimapTest
     * @Description: Muitimap 就是一个 key 对应多个 value 的数据结构。Muitimap 是 :{k1=[v1, v2, v3], k2=[v7, v8],....}。
     * @author: FLY
     * @date: 2018-06-23 7:04
     */
    public static void MultimapTest() {
        Multimap<String, Integer> map = HashMultimap.create(); //Multimap是把键映射到任意多个值的一般方式
        map.put("FLY", 1); //key相同时不会覆盖原value
        map.put("FLY", 2);
        map.put("FLY", 3);
        map.put("ALEX", 4);
        map.put("ALEX", 5);
        System.out.println(map); //{ALEX=[4, 5], FLY=[1, 2, 3]}
        System.out.println(map.get("FLY")); //返回的是集合  // [1, 2, 3]
        System.out.println(map.size()); //返回所有”键-单个值映射”的个数,而非不同键的个数 // 5
        System.out.println(map.keySet().size()); //返回不同key的个数 // 2
        Map<String, Collection<Integer>> mapView = map.asMap();
        System.out.println(mapView);// {ALEX=[4, 5], FLY=[1, 2, 3]}
    }



BiMap: 保证 value 也不重复

BiMap<K, V>是特殊的Map:

  • 可以用 inverse()反转BiMap<K, V>的键值映射
  • 保证值是唯一的,因此 values()返回Set而不是普通的Collection
/**
     * @param
     * @return void
     * @Title: BiMap: 双向 Map
     * @methodName: BiMapTest
     * @Description: 它的特点是它的 value 和它 key 一样也是不可重复的,换句话说它的 key 和 value 是等价的。
     * 如果你往 BiMap 的 value 里面放了重复的元素,就会得到 IllegalArgumentException。
     * @author: FLY
     * @date: 2018-06-25 6:28
     */
    public static void BiMapTest() {
        BiMap<Integer, String> empIDNameMap = HashBiMap.create();
        empIDNameMap.put(new Integer(101), "Mahesh");
        empIDNameMap.put(new Integer(102), "Sohan");
        empIDNameMap.put(new Integer(103), "Ramesh");
        // empIDNameMap.put(new Integer(104), "Mahesh"); // 报错:  java.lang.IllegalArgumentException: value already present: Mahesh
        //Emp Id of Employee "Mahesh"
        System.out.println(empIDNameMap.inverse().get("Mahesh"));
    }


MapMaker: 超级强大的 Map 构造类

/**
     * @Title: MapMaker: 超级强大的 Map 构造工具
     * @methodName: MapMakerTest
     * @param
     * @return void
     * @Description:
     *
     * @author: 王延飞
     * @date: 2018-06-27 6:51
     */
    public static void  MapMakerTest() {
        //MapMaker 是用来构造 ConcurrentMap 的工具类。它可以用来构造ConcurrentHashMap:得到线程安全的hashMap
        //ConcurrentHashMap with concurrency level 8
        ConcurrentMap<String, Object> map1 = new MapMaker()
                .concurrencyLevel(8)
                .makeMap();
    }

Collections2: 过滤器-Filter

/**
     * @Title:  Collections2.filter() 方法过滤集合中不符合条件的元素
     * @methodName: Collections2FilterTest
     * @param
     * @return void
     * @Description:
     *
     * @author: 王延飞
     * @date: 2018-06-28 7:02
     */
    public static void  Collections2FilterTest() {
        ArrayList<Integer> list =  Lists.newArrayList(1,2,5,6,8,9,4,11,23,45,56,78);
        // 过滤一个 List<Integer> 里面大于 10 的元素 :
        Collection<Integer>  filterCollection =
                Collections2.filter(list, new Predicate<Integer>(){
                    @Override
                    public boolean apply(Integer input) {
                        return input <= 10;
                    }});
        System.out.println("filterCollection:"+filterCollection); // filterCollection:[1, 2, 5, 6, 8, 9, 4]
    }

Collections2: 转换器-Transform

 /**
     * @Title: 转换器
     * @methodName: Collections2TransformTest
     * @param
     * @return void
     * @Description: 利用 Collections2.transform() 方法来转换集合中的元素
     *
     * @author: 王延飞
     * @date: 2018-06-28 7:37
     */
    public static void  Collections2TransformTest() {
        // 把一个 Set<Integer> 里面所有元素都转换成带格式的 String 来产生新的 Collection<String>:
        Collection<Integer> set = Lists.newArrayList(1123,4590,5667,7800);
        Collection<String>  transformtCollection =
                Collections2.transform(set, input -> new DecimalFormat("#,###").format(input));
        System.out.println("transformtCollection:"+transformtCollection); // transformtCollection:[1,123, 4,590, 5,667, 7,800]
    }



目录
相关文章
|
存储 设计模式 缓存
Java源码分析:Guava之不可变集合ImmutableMap的源码分析
Java源码分析:Guava之不可变集合ImmutableMap的源码分析
62 0
|
7月前
|
消息中间件 存储 缓存
Guava的这些骚操作让我的代码量减少了50行
Guava的这些骚操作让我的代码量减少了50行
46 3
|
Java
Guava Lists工具类
Guava Lists工具类
77 0
|
消息中间件 缓存 JavaScript
Guava的这些骚操作,让我的代码量减少了50%
Guava的这些骚操作,让我的代码量减少了50%
|
存储 缓存 Java
Guava中这些Map的骚操作,让我的代码量减少了50%
Guava是google公司开发的一款Java类库扩展工具包,内含了丰富的API,涵盖了集合、缓存、并发、I/O等多个方面。使用这些API一方面可以简化我们代码,使代码更为优雅,另一方面它补充了很多jdk中没有的功能,能让我们开发中更为高效。
188 0
|
安全 Java Maven
Guava 如何让 Map 不可变之 ImmutableMap
Guava 如何让 Map 不可变之 ImmutableMap
420 0
Guava 如何让 Map 不可变之 ImmutableMap
|
Java 测试技术
Guava常用集合操作API
Guava常用集合操作API
368 0
|
数据采集 缓存 算法
Guava的布隆过滤器
 程序世界的算法都要在时间,资源占用甚至正确率等多种因素间进行平衡。同样的问题,所属的量级或场景不同,所用算法也会不同,其中也会涉及很多的trade-off。 If there’s one rule in programming, it’s this: there will always be trade-offs. 你是否真的存在  今天我们就来探讨如何判断一个值是否存在于已有的集合问题。
|
存储
guava学习:guava集合类型-Bimap
学习guava让我惊喜的第二个接口就是:Bimap BiMap是一种特殊的映射其保持映射,同时确保没有重复的值是存在于该映射和一个值可以安全地用于获取键背面的倒数映射。 最近开发过程中,经常会有这种根据key找value或者根据value找key 的功能,之前都是将值存储到枚举或者map中,然后通过反转的写法来实现的,直到发现了Bimap,才发现原来还有这么简便的方式。
1234 0