0
点赞
收藏
分享

微信扫一扫

[EFI]Dell Inspiron 15 5567 电脑 Hackintosh 黑苹果efi引导文件

巧乐兹_d41f 04-02 19:30 阅读 2

Java9为集合接口List、Set、Map提供了创建不可变实例的工厂方法。这些工厂方法为便利而生,以简单的方式创建这些集合的不可变实例。

Java9之前创建不可变集合

在Java9之前,创建不可变集合通常需要通过其他方式,比如使用Collections.unmodifiableList()Collections.unmodifiableSet()Collections.unmodifiableMap()等方法来包装一个可变集合,使其变为不可变。

package com.morris.java9;

import java.util.*;

/**
 * Java8创建不可变集合
 */
public class Collection8Demo {
    public static void main(String[] args) {
        // 创建不可变List
        List<String> mutableList = new ArrayList<>(Arrays.asList("one", "two", "three"));
        List<String> immutableList = Collections.unmodifiableList(mutableList);
        System.out.println(immutableList);
        mutableList.add("four");
        System.out.println(immutableList);

        // 创建不可变Set
        Set<String> mutableSet = new HashSet<>(Arrays.asList("one", "two", "three"));
        Set<String> immutableSet = Collections.unmodifiableSet(mutableSet);
        System.out.println(immutableSet);

        // 创建不可变Map
        Map<String, Integer> mutableMap = new HashMap<>();
        mutableMap.put("one", 1);
        mutableMap.put("two", 2);
        Map<String, Integer> immutableMap = Collections.unmodifiableMap(mutableMap);
        System.out.println(immutableMap);
    }
}

运行结果如下:

[one, two, three]
[one, two, three, four]
[one, two, three]
{one=1, two=2}

创建可变集合很简单,但是创建不可变集合则先需要创建一个可变集合,然后再使用Collections.unmodifiableXxx来创建不可变集合。为什么会这么复杂?因为不可变集合一旦创建元素是固定的,也就无法使用add/put/remove等方法来修改集合中的元素。

Collections.unmodifiableList()的底层会使用静态代理模式将原来的ArrayList封装为UnmodifiableList类,对UnmodifiableList类的修改操作都会抛出异常,UnmodifiableList类的add/put/remove方法源码如下:

public E set(int index, E element) {
    throw new UnsupportedOperationException();
}
public void add(int index, E element) {
    throw new UnsupportedOperationException();
}
public E remove(int index) {
    throw new UnsupportedOperationException();
}

然而,这种方式仍然依赖于原始的可变集合,如果原始集合被修改,那么这些不可变集合的行为就会变得不可预测。在上面的例子中可以看到对原始集合进行添加元素,不可变集合中的元素也被修改了。

Java9创建不可变集合

在Java9中,为集合接口(List、Set、Map)提供了创建不可变实例的工厂方法,其中最常用的方法是of()。这个方法用于定义三种集合的不可变实例,参数即为不可变实例的所有元素。

package com.morris.java9;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Java9创建不可变集合
 */
public class Collection9Demo {
    public static void main(String[] args) {
        // 创建不可变List
        List<String> immutableList = List.of("one", "two", "three");
        System.out.println(immutableList);

        // 创建不可变Set
        Set<String> immutableSet = Set.of("one", "two", "three");
        System.out.println(immutableSet);

        // 创建不可变Map
        Map<String, Integer> immutableMap = Map.of("one", 1, "two", 2);
        System.out.println(immutableMap);
    }
}

运行结果如下:

[one, two, three]
[three, two, one]
{two=2, one=1}

对于List、Set和Map三个接口的of()方法,重载方法的参数有0~10个不等。如果要创建的不可变集合的元素数量超过了10个,就不能再用of()方法了。

对于List和Set的of()方法,重载方法还包含了一个参数args用于接受数量不定的值,这样就可以创建包含任意数量的List、Set。

List的12个重载of()方法:

static <E> List<E> of() {
    return (List<E>) ImmutableCollections.EMPTY_LIST;
}
    
static <E> List<E> of(E e1) {
    return new ImmutableCollections.List12<>(e1);
}

static <E> List<E> of(E e1, E e2) {
    return new ImmutableCollections.List12<>(e1, e2);
}

static <E> List<E> of(E e1, E e2, E e3) {
    return ImmutableCollections.listFromTrustedArray(e1, e2, e3);
}

static <E> List<E> of(E e1, E e2, E e3, E e4) {
    return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4);
}

static <E> List<E> of(E e1, E e2, E e3, E e4, E e5) {
    return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5);
}

static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {
    return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5,
                                                     e6);
}

static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {
    return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5,
                                                     e6, e7);
}

static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {
    return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5,
                                                     e6, e7, e8);
}

static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {
    return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5,
                                                     e6, e7, e8, e9);
}

static <E> List<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {
    return ImmutableCollections.listFromTrustedArray(e1, e2, e3, e4, e5,
                                                     e6, e7, e8, e9, e10);
}

static <E> List<E> of(E... elements) {
    switch (elements.length) { // implicit null check of elements
        case 0:
            @SuppressWarnings("unchecked")
            var list = (List<E>) ImmutableCollections.EMPTY_LIST;
            return list;
        case 1:
            return new ImmutableCollections.List12<>(elements[0]);
        case 2:
            return new ImmutableCollections.List12<>(elements[0], elements[1]);
        default:
            return ImmutableCollections.listFromArray(elements);
    }
}

Set和List一样,同样有12个重载of()方法。

而如果要创建的不可变哈希(HashMap)的数量超过了10个,就不能再用of()方法了,而需要使用ofEntries方法。

Map.ofEntries()的使用如下:

package com.morris.java9;

import java.util.Map;

/**
 * Map.ofEntries(),创建的不可变哈希(HashMap)的数量超过了10个使用
 */
public class MapOfEntriesDemo {
    public static void main(String[] args) {
        Map<Integer, String> map = Map.ofEntries(
                Map.entry(1, "a"),
                Map.entry(2, "b"),
                Map.entry(3, "c"),
                Map.entry(26, "z"));
        System.out.println(map);
    }
}

除了of()方法,Java还提供了copyOf()方法,这个方法可以用来创建一个包含另一个集合所有元素的不可变版本。

List.copyOf()的使用如下:

package com.morris.java9;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * List.copyOf,创建一个包含另一个集合所有元素的不可变版本
 */
public class ListCopyOfDemo {
    public static void main(String[] args) {
        List<String> mutableList = new ArrayList<>(Arrays.asList("one", "two", "three"));
        // 创建不可变List
        List<String> immutableList = List.copyOf(mutableList);
        mutableList.add("four");
        System.out.println(immutableList);
    }
}

运行结果如下:

[one, two, three]

从运行结果可以看出,原集合的修改不影响新集合。

List.copyOf()方法的源码如下:

static <E> List<E> copyOf(Collection<? extends E> coll) {
    return ImmutableCollections.listCopy(coll);
}

static <E> List<E> listCopy(Collection<? extends E> coll) {
  if (coll instanceof List12 || (coll instanceof ListN<?> c && !c.allowNulls)) {
      return (List<E>)coll;
  } else if (coll.isEmpty()) { // implicit nullcheck of coll
      return List.of();
  } else {
      return (List<E>)List.of(coll.toArray());
  }
}

List.copyOf()方法底层使用List.of()来构建不可变集合。

对比两者的区别

安全性

在Java 9之前,虽然使用了Collections.unmodifiableXXX()方法,但是如果原始的可变集合被修改,那么不可变集合的语义就会被破坏,可能会导致UnsupportedOperationException异常。

在Java 9及以后,使用工厂方法创建的集合是真正不可变的,不依赖于任何外部可变集合,因此更加安全。

简洁性

Java 9之前的做法需要首先创建一个可变集合,然后再调用Collections.unmodifiableXXX()来创建不可变版本,代码相对繁琐。

Java 9及以后的做法直接通过工厂方法一步到位,代码更加简洁。

性能

工厂方法创建的不可变集合在内部实现上可能进行了优化,因此可能在某些情况下具有更好的性能。

灵活性

Java 9之前的做法在处理大量元素时可能需要额外的步骤,例如使用Arrays.asList()或循环添加元素到集合中。

Java 9的工厂方法提供了多个重载版本,可以方便地处理不同数量的元素,同时还可以通过copyOf()方法从现有集合创建不可变版本,提供了更多的灵活性。

总的来说,Java 9引入的集合不可变实例工厂方法提高了创建不可变集合的便捷性、安全性和性能,是Java集合API的一个显著改进。

在这里插入图片描述

举报

相关推荐

0 条评论