Java中的不可变集合,咱们换个方式理解!!!

不可变集合例:

public static final ImmutableSet<String> COLOR_NAMES = ImmutableSet.of(
        "red",
        "orange",
        "yellow",
        "green",
        "blue",
        "purple");

class Foo {
    Set<Bar> bars;
    Foo(Set<Bar> bars) {
        this.bars = ImmutableSet.copyOf(bars); // defensive copy!
    }
}

为何要使用不可变集合

不可变对象有不少优势,包括:java

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

建立对象的不可变拷贝是一项很好的防护性编程技巧。Guava为全部JDK标准集合类型和Guava新集合类型都提供了简单易用的不可变版本。
JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式,但咱们认为不够好:面试

  • 笨重并且累赘:不能温馨地用在全部想作防护性拷贝的场景;
  • 不安全:要保证没人经过原集合的引用进行修改,返回的集合才是事实上不可变的;
  • 低效:包装过的集合仍然保有可变集合的开销,好比并发修改的检查、散列表的额外空间,等等。

若是你没有修改某个集合的需求,或者但愿某个集合保持不变时,把它防护性地拷贝到不可变集合是个很好的实践。算法

重要提示:全部Guava不可变集合的实现都不接受null值。咱们对Google内部的代码库作过详细研究,发现只有5%的状况须要在集合中容许null元素,剩下的95%场景都是遇到null值就快速失败。若是你须要在不可变集合中使用null,请使用JDK中的Collections.unmodifiableXXX方法。更多细节建议请参考“使用和避免null”。spring

怎么使用不可变集合

不可变集合能够用以下多种方式建立:数据库

  • copyOf方法,如ImmutableSet.copyOf(set);
  • of方法,如ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2);
  • Builder工具,如
public static final ImmutableSet<Color> GOOGLE_COLORS =
        ImmutableSet.<Color>builder()
            .addAll(WEBSAFE_COLORS)
            .add(new Color(0, 191, 255))
            .build();

此外,对有序不可变集合来讲,排序是在构造集合的时候完成的,如:编程

ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");

会在构造时就把元素排序为a, b, c, d。设计模式

比想象中更智能的copyOf

请注意,ImmutableXXX.copyOf方法会尝试在安全的时候避免作拷贝——实际的实现细节不详,但一般来讲是很智能的,好比:缓存

ImmutableSet<String> foobar = ImmutableSet.of("foo", "bar", "baz");
thingamajig(foobar);

void thingamajig(Collection<String> collection) {
    ImmutableList<String> defensiveCopy = ImmutableList.copyOf(collection);
    ...
}

在这段代码中,ImmutableList.copyOf(foobar)会智能地直接返回foobar.asList(),它是一个ImmutableSet的常量时间复杂度的List视图。
做为一种探索,ImmutableXXX.copyOf(ImmutableCollection)会试图对以下状况避免线性时间拷贝:安全

  • 在常量时间内使用底层数据结构是可能的——例如,ImmutableSet.copyOf(ImmutableList)就不能在常量时间内完成。
  • 不会形成内存泄露——例如,你有个很大的不可变集合ImmutableList
    hugeList, ImmutableList.copyOf(hugeList.subList(0, 10))就会显式地拷贝,以避免没必要要地持有hugeList的引用。
  • 不改变语义——因此ImmutableSet.copyOf(myImmutableSortedSet)会显式地拷贝,由于和基于比较器的ImmutableSortedSet相比,ImmutableSet对hashCode()和equals有不一样语义。
    在可能的状况下避免线性拷贝,能够最大限度地减小防护性编程风格所带来的性能开销。

asList视图

全部不可变集合都有一个asList()方法提供ImmutableList视图,来帮助你用列表形式方便地读取集合元素。例如,你可使用sortedSet.asList().get(k)从ImmutableSortedSet中读取第k个最小元素。数据结构

asList()返回的ImmutableList一般是——并不老是——开销稳定的视图实现,而不是简单地把元素拷贝进List。也就是说,asList返回的列表视图一般比通常的列表平均性能更好,好比,在底层集合支持的状况下,它老是使用高效的contains方法。

最后

私信回复 资料 领取一线大厂Java面试题总结+阿里巴巴泰山手册+各知识点学习思惟导+一份300页pdf文档的Java核心知识点总结!

在这里插入图片描述

这些资料的内容都是面试时面试官必问的知识点,篇章包括了不少知识点,其中包括了有基础知识、Java集合、JVM、多线程并发、spring原理、微服务、Netty 与RPC 、Kafka、日记、设计模式、Java算法、数据库、Zookeeper、分布式缓存、数据结构等等。
file

相关文章
相关标签/搜索