Java 把一个Stream收集到一个不可变的Collection中

Java 把一个Stream收集到一个不可变的Collection中

Stream和Collection是在Java 8中引入的,引入了流的概念。一个流是一个序列,一个对象的序列。我们从数组、列表等输入源生成流,并支持过滤、映射、限制、减少等聚合操作。我们使用流来处理数据,最终将其收集到某种形式的收集器中。采集器只不过是用来存储流处理结果的容器。采集器可以是一个List、Map或Set。

一个不可变的集合是一个一旦创建就不能改变其值的集合。我们确实需要不可变的集合,因为很多时候我们可以有不改变的数据集合,即查找列表。例如,一年中的几个月或一周中的几天的列表,等等。让这样的列表(其中的数据不会改变)成为不可更改的,使它们更节省内存和空间。它们在本质上也是线程安全的。一般来说,不可变的对象需要的内存比可变的对象少得多。

如果一个对象在构建后其状态不能改变,则被认为是不可变的。在你创建了一个集合的不可变实例后,只要有对它的引用存在,它就会持有相同的数据。

方法: 根据Java版本的不同,有多种方法可用于创建不可更改的对象,随着Java版本的进步,我们可以用这些方法创建不可更改的集合。

  1. Java 10之前
    • 创建流并使用 “collectingAndThen” 将其收集到一个不可修改的结构中。
    • 谷歌的Guava库
  2. Java 10之后
    • toUnmodifiableList()
    • 解释为:toUnmodifiableMap()
    • toUnmodifiableSet()

情景1:Java 10之前

方法1: 创建流并将其收集到一个不可修改的结构中。在Java 10之前,没有直接的方法可以在Java中创建一个不可变的集合。一种方法是创建一个Stream,并使用”collectingAndThen“方法将其收集到一个不可修改的结构中。

示例:

// Java Program to illustrate Collecting a Stream to an
// Immutable Collection
// Pre java 10
// Using collectingAndThen method
 
// Importing Collections, Collectors and Stream classes
// from java.util package
import java.util.Collections;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
// Main class
// PreJava10ImmutableCollections
public class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Custom inputs integer elements in List
        var unmodifiableList
            = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
                  .collect(Collectors.collectingAndThen(
                      Collectors.toList(),
                      Collections::unmodifiableList));
 
        System.out.println(unmodifiableList);
 
        // Operations like this will result in an exception
        unmodifiableList.add(12);
    }
}
Java

输出:

在Java中把一个流收集到一个不可变的集合中

方法2: 使用谷歌的Guava库。为此,需要一个前提工作,那就是包含JAR文件。Guava库的JAR是下载jar并将其添加到eclipse的构建路径中。Guava库提供了ImmutableList类。下面是一个例子。

示例:

// Java Program to illustrate Collecting a
// Stream to an Immutable Collection
// Pre java 10  Using Google’s Guava library
 
// Importing Guava library
import com.google.common.collect.ImmutableList;
// Importing classes from java.util package
import java.util.List;
import java.util.stream.IntStream;
 
// Main class
public class PreJava10ImmutableCollections {
 
    // main driver method
    public static void main(String[] args) {
 
        // Using the Guava Libraries
        List<Integer> someList
            = IntStream.range(0, 15).boxed().collect(
                  ImmutableList.toImmutableList());
 
        // Print and display the elements
        System.out.println(someList);
    }
}
Java

输出:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
Java

注意: 我们也可以实现自己的版本来创建不可变的list、map或set。

情况2:Java版本10及以上

Java第10版通过Collectors类引入了创建Immutable集合的功能。我们有3个方法,一个用于List,一个用于Set,还有一个用于Map。

方法1: .假设我们有一个前50个偶数的流,并从中创建一个不可变的列表。

示例:

// Java Program to illustrate Collecting a Stream to
// an Immutable Collection
// Post java 10
// using toUnmodifiableList() method
 
// Importing classes from java.util package
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
// Main Class
// ImmutableCollectionList
public class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating Stream class object of integer type
        Stream<Integer> evenNumberStream
            = Stream.iterate(0, i -> i + 2).limit(50);
 
        // Creating List class object of integer type
        List<Integer> evenNumbers
            = (List<Integer>)evenNumberStream.collect(
                Collectors.toUnmodifiableList());
 
        // Print all elements in the List object
        System.out.println(evenNumbers);
 
        // These will result in
        // java.lang.UnsupportedOperationException
 
        evenNumbers.add(90);
        // evenNumbers.remove(1);
    }
}
Java

输出:

在Java中把一个流收集到一个不可变的集合中

方法2: 使用toUnmodifiableMap()方法

考虑一个书籍类的例子。图书对象有两个参数,即’Id’和’Name’。我们将生成一个书籍对象的流。假设我们必须从这个对象的集合中生成一个不可变的Map。要做到这一点,我们使用toUnmodifiableMap()函数。

示例:

// Java Program to illustrate Collecting a Stream to
// an Immutable Collection
// Post java 10
// Using toUnmodifiableMap() method
 
// Importing required libraries
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
// Main Class
// ImmutableCollectionMap
public class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
 
        // Creating a Map from a Stream of books by
        // creating an object of List class of books type
        List<Books> libInventory = new ArrayList<Books>();
 
        // Adding elements to the above object created
        // Custom input entries
        libInventory.add(
            new Books(1, "Pride and Prejudice"));
        libInventory.add(new Books(2, "The Sign of Four"));
        libInventory.add(
            new Books(3, "Sense and Sensibility"));
        libInventory.add(new Books(4, "Mansfield Park"));
        libInventory.add(
            new Books(5, "The Materese Circle"));
        libInventory.add(
            new Books(6, "The Hound of Baskerville"));
        libInventory.add(new Books(7, "Goodnight Moon"));
        libInventory.add(new Books(
            8, "How many sleeps till my Birthday"));
        libInventory.add(
            new Books(9, "The Bourne Identity"));
        libInventory.add(new Books(10, "Murder She Wrote"));
        libInventory.add(new Books(
            11, "The adventures of Hercule Poirot"));
        libInventory.add(
            new Books(12, "The song of Ice and Fire"));
 
        // Creating a Map class object
        // Declaring object of integer and string type
        Map<Integer, String> unmutableInventory
            = libInventory.stream().collect(
                Collectors.toUnmodifiableMap(
                    Books::getBookNumber,
                    Books::getBookName));
 
        // Print all the elements in the Map object created
        // above
        System.out.println(unmutableInventory);
 
        // This will result in an Exception
        unmutableInventory.put(13, "Some book");
    }
}
Java

输出:

在Java中把一个流收集到一个不可变的集合中

方法3: 使用toUnmodifiableSet()方法

实施情况: 从一个流中创建一个不可修改的集合,要做到这一点,我们使用toUnmodifiableSet()函数。

// Java Program to illustrate Collecting a Stream to
// an Immutable Collection
// Post java 10
// Using toUnmodifiableSet() method
 
// Importing required libraries
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
 
// Main class
// ImmutableCollectionSet
public class GFG {
 
    // Main driver method
    public static void main(String[] args)
    {
        // Creating Stream object of type Double
        Stream<Double> randomDecimals
            = Stream.generate(Math::random).limit(30);
 
        // Now creating Set class object of type Double
        Set<Double> randomSet = randomDecimals.collect(
            Collectors.toUnmodifiableSet());
 
        // Print and display elements in Set object
        System.out.println(randomSet);
 
        // This will produce an exception
        randomSet.add(100.0);
    }
}
Java

在Java中把一个流收集到一个不可变的集合中

结论: 在这里,我们看到了如何在Java中从一个流中创建不可变的集合。我们还看到了根据所使用的Java版本,用来创建集合的不同方法。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

登录

注册