【java代码之美】---guava之Immutable(不可变)集合

Immutable(不可变)集合

一、概述

guava是google的一个库,弥补了java语言的很多方面的不足,很多在java8中已有实现,暂时不展开。Collections是jdk提供的一个工具类。

Guava中不可变对象和Collections工具类的unmodifiableSet/List/Map/etc的区别:

当Collections创建的不可变集合的wrapper类改变的时候,不可变集合也会改变,而Guava的Immutable集合保证确实是不可变的。

1、JDK中实现immutable集合

在JDK中提供了Collections.unmodifiableXXX系列方法来实现不可变集合, 但是存在一些问题,下面我们先看一个具体实例:

public class ImmutableTest {

    @Test
    public void testJDKImmutable(){
        List<String> list=new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");

        //通过list创建一个不可变的unmodifiableList集合
        List<String> unmodifiableList=Collections.unmodifiableList(list);
        System.out.println(unmodifiableList);

        //通过list添加元素
        list.add("ddd");
        System.out.println("往list添加一个元素:"+list);
        System.out.println("通过list添加元素之后的unmodifiableList:"+unmodifiableList);

        //通过unmodifiableList添加元素
        unmodifiableList.add("eee");
        System.out.println("往unmodifiableList添加一个元素:"+unmodifiableList);

    }
}

运行结果:

通过运行结果我们可以看出:虽然unmodifiableList不可以直接添加元素,但是我的list是可以添加元素的,而list的改变也会使unmodifiableList改变。

所以说Collections.unmodifiableList实现的不是真正的不可变集合。

2、Guava的immutable集合

Guava提供了对JDK里标准集合类里的immutable版本的简单方便的实现,以及Guava自己的一些专门集合类的immutable实现。当你不希望修改一个集合类,

或者想做一个常量集合类的时候,使用immutable集合类就是一个最佳的编程实践。

注意:每个Guava immutable集合类的实现都拒绝null值。我们做过对Google内部代码的全面的调查,并且发现只有5%的情况下集合类允许null值,而95%的情况下

都拒绝null值。万一你真的需要能接受null值的集合类,你可以考虑用Collections.unmodifiableXXX。

immutable集合可以有以下几种方式来创建:

  1、用copyOf方法, 譬如, ImmutableSet.copyOf(set)

  2、使用of方法,譬如,ImmutableSet.of("a", "b", "c")或者ImmutableMap.of("a", 1, "b", 2)

  3、使用Builder类

举例:

 @Test
    public void testGuavaImmutable(){

        List<String> list=new ArrayList<String>();
        list.add("a");
        list.add("b");
        list.add("c");

        ImmutableList<String> imlist=ImmutableList.copyOf(list);
        System.out.println("imlist:"+imlist);

        ImmutableList<String> imOflist=ImmutableList.of("peida","jerry","harry");
        System.out.println("imOflist:"+imOflist);

        ImmutableSortedSet<String> imSortList=ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");
        System.out.println("imSortList:"+imSortList);

        list.add("baby");
        //关键看这里是否imlist也添加新元素了
        System.out.println("list添加新元素之后看imlist:"+imlist);

        ImmutableSet<Color> imColorSet =
                ImmutableSet.<Color>builder()
                        .add(new Color(0, 255, 255))
                        .add(new Color(0, 191, 255))
                        .build();

        System.out.println("imColorSet:"+imColorSet);
    }

运行结果:发现imlist并未改变。

对于排序的集合来说有例外,因为元素的顺序在构建集合的时候就被固定下来了。譬如,ImmutableSet.of("a", "b", "c", "a", "d", "b"),对于这个集合的遍历顺序来说就是"a", "b", "c", "d"。

更智能的copyOf

copyOf方法比你想象的要智能,ImmutableXXX.copyOf会在合适的情况下避免拷贝元素的操作-先忽略具体的细节,但是它的实现一般都是很“智能”的。譬如:

  @Test
        public void testCotyOf(){
            ImmutableSet<String> imSet=ImmutableSet.of("peida","jerry","harry","lisa");
            System.out.println("imSet:"+imSet);

            //set直接转list
            ImmutableList<String> imlist=ImmutableList.copyOf(imSet);
            System.out.println("imlist:"+imlist);

            //list直接转SortedSet
            ImmutableSortedSet<String> imSortSet=ImmutableSortedSet.copyOf(imSet);
            System.out.println("imSortSet:"+imSortSet);

            List<String> list=new ArrayList<String>();
            for(int i=0;i<=10;i++){
                list.add(i+"x");
            }
            System.out.println("list:"+list);

            //截取集合部分元素
            ImmutableList<String> imInfolist=ImmutableList.copyOf(list.subList(2, 8));
            System.out.println("imInfolist:"+imInfolist);
        }

运行结果

Guava集合和不可变对应关系

可变集合类型 可变集合源:JDK or Guava? Guava不可变集合
Collection JDK ImmutableCollection
List JDK ImmutableList
Set JDK ImmutableSet
SortedSet/NavigableSet JDK ImmutableSortedSet
Map JDK ImmutableMap
SortedMap JDK ImmutableSortedMap
Multiset Guava ImmutableMultiset
SortedMultiset Guava ImmutableSortedMultiset
Multimap Guava ImmutableMultimap
ListMultimap Guava ImmutableListMultimap
SetMultimap Guava ImmutableSetMultimap
BiMap Guava ImmutableBiMap
ClassToInstanceMap Guava ImmutableClassToInstanceMap
Table Guava ImmutableTable

本文参考:Guava学习笔记:Immutable(不可变)集合 感谢!

 想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。中校【12】

原文地址:https://www.cnblogs.com/qdhxhz/p/9404654.html

时间: 2024-10-07 10:58:02

【java代码之美】---guava之Immutable(不可变)集合的相关文章

java代码之美(14)---Java8 函数式接口

Java8 函数式接口 之前写了有关JDK8的Lambda表达式:java代码之美(1)---Java8 Lambda 函数式接口可以理解就是为Lambda服务的,它们组合在一起可以让你的代码看去更加简洁. 一.概念 1.什么是函数式接口 概念 所谓的函数式接口, 当然首先是一个接口, 然后就是在这个接口里面 只能有一个抽象方法. 有关函数式接口,有个专门的注解叫:@FunctionalInterface.该注解主要特点有: 1.该注解只能标记在"有且仅有一个抽象方法"的接口上,表示函

java代码之美(16) ---Java8 Optional

摘自:https://www.cnblogs.com/qdhxhz/p/12056745.html Java8 Optional 一句话介绍Optional类:使用JDK8的Optional类来防止NullPointerException(空指针异常)问题. 一.前言 在我们开放过程中,碰到的异常中NullPointerException必然是排行第一的.所以在平时编码中,我们会时时的判断null. public void saveCity(City city) { if (city != nu

【java代码之美】---Java8 Map中的computeIfAbsent方法

Map中的computeIfAbsent方法 Map接口的实现类如HashMap,ConcurrentHashMap,HashTable等继承了此方法,通过此方法可以在特定需求下,让你的代码更加简洁. 一.案例说明 1.概述 在JAVA8的Map接口中,增加了一个方法computeIfAbsent,此方法签名如下: public V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction) 此方法首先判断缓存

Guava学习笔记:Immutable(不可变)集合

不可变集合,顾名思义就是说集合是不可被修改的.集合的数据项是在创建的时候提供,并且在整个生命周期中都不可改变. 为什么要用immutable对象?immutable对象有以下的优点: 1.对不可靠的客户代码库来说,它使用安全,可以在未受信任的类库中安全的使用这些对象 2.线程安全的:immutable对象在多线程下安全,没有竞态条件 3.不需要支持可变性, 可以尽量节省空间和时间的开销. 所有的不可变集合实现都比可变集合更加有效的利用内存 (analysis) 4.可以被使用为一个常量,并且期望

Immutable(不可变)集合

不可变集合,顾名思义就是说集合是不可被修改的.集合的数据项是在创建的时候提供,并且在整个生命周期中都不可改变. 为什么要用immutable对象?immutable对象有以下的优点: 1.对不可靠的客户代码库来说,它使用安全,可以在未受信任的类库中安全的使用这些对象 2.线程安全的:immutable对象在多线程下安全,没有竞态条件 3.不需要支持可变性, 可以尽量节省空间和时间的开销. 所有的不可变集合实现都比可变集合更加有效的利用内存 (analysis) 4.可以被使用为一个常量,并且期望

【java代码之美】---Java8 Stream

Stream 第一次看到Stream表达式就深深把我吸引,用它可以使你的代码更加整洁而且对集合的操作效率也会大大提高,如果你还没有用到java8的Stream特性,那就说明你确实out啦. 一.概述 1.什么是Stream Stream是一种可供流式操作的数据视图有些类似数据库中视图的概念它不改变源数据集合如果对其进行改变的操作它会返回一个新的数据集合. 总的来讲它有三大特性:在之后我们会对照着详细说明        1.stream不存储数据        2.stream不改变源数据    

MySQL巧用FIND_IN_SET和GROUP_CONCAT函数减少Java代码量

数据库表简介:物品表 `id` int(11)  '物品id,唯一标识', `name` varchar(255) '物品名称', `level` int(11) '物品类别等级,礼品包为最高级1,类别为2级,详细物品为3级', `parentId` int(11) '只有3级详细物品有上级id', `childIds` varchar(255)  '只有1级礼品包级有包含所有3级物品id的字符串,id之间用","隔开', 问题描述:利用sql语句简化代码,让Java代码可以直接通过j

Java集合类汇总记录--guava篇

BiMap HashBiMap<K,V> 实现了两份哈希表数据结构(本类独立实现),分别负责两个方向的映射. EnumBiMap<K,V> 两个EnumMap对象分别负责两个方向的映射. EnumHashBiMap<K,V> 一个EnumMap对象负责K到V映射,一个HashMap对象负责V到K的影身. MultiMap HashMultimap<K,V> 使用HashMap<K,HashSet<V>>对象实现. TreeMultim

如何写出更好的Java代码

Java是最流行的编程语言之一,但似乎并没有人喜欢使用它.好吧,实际上Java是一门还不错的编程语言,由于最近Java 8发布了,我决定来编辑一个如何能更好地使用Java的列表,这里面包括一些库,实践技巧以及工具. 这篇文章在GitHub上也有.你可以随时在上面贡献或者添加你自己的Java使用技巧或者最佳实践. 编码风格 结构体 builder模式 依赖注入 避免null值 不可变 避免过多的工具类 格式 文档 Stream 部署 框架 Maven 依赖收敛 持续集成 Maven仓储 配置管理