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]
    }

猜你喜欢

转载自blog.csdn.net/fly910905/article/details/80818575