📜  在Java中将流收集到不可变集合

📅  最后修改于: 2022-05-13 01:54:31.846000             🧑  作者: Mango

在Java中将流收集到不可变集合

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

不可变集合是一个集合,其值一旦创建就无法更改。我们确实需要不可变的集合,因为很多时候我们可以拥有不变的数据集合,即查找列表。例如,一年中的月份列表或一周中的几天等。使此类列表(具有不变的数据)不可变可以使它们更有效地节省内存和空间。它们本质上也是线程安全的。通常,不可变对象需要比可变对象少得多的内存。

方法:根据Java版本,根据我们可以创建不可变集合的Java版本的进步,可以使用多种方法来创建不可变对象。

  1. Java 10 之前的版本
    • 创建 Stream 并使用“ collectionAndThen ”将其收集到不可修改的结构中
    • 谷歌的番石榴库
  2. 在Java 10 之后
    • toUnmodifiableList()
    • toUnmodifiableMap()
    • toUnmodifiableSet()

场景 1:Java 10 之前的版本

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



例子:

Java
// 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 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 someList
            = IntStream.range(0, 15).boxed().collect(
                  ImmutableList.toImmutableList());
 
        // Print and display the elements
        System.out.println(someList);
    }
}


Java
// 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 evenNumberStream
            = Stream.iterate(0, i -> i + 2).limit(50);
 
        // Creating List class object of integer tpye
        List evenNumbers
            = (List)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 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 libInventory = new ArrayList();
 
        // 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 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 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 randomDecimals
            = Stream.generate(Math::random).limit(30);
 
        // Now creating Set class object of type Double
        Set 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);
    }
}


输出:

方法二:使用谷歌的番石榴库。为此,需要一个先决条件,即包含 JAR 文件。 Guava 库的JAR 就是下载jar 并添加到eclipse 中的构建路径中。 Guava 库提供了 ImmutableList 类。下面给出相同的示例。

例子:

Java

// 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 someList
            = IntStream.range(0, 15).boxed().collect(
                  ImmutableList.toImmutableList());
 
        // Print and display the elements
        System.out.println(someList);
    }
}

输出:



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

场景 2: Java 10 及以上版本

Java版本 10 引入了通过 Collectors 类创建不可变集合的函数。我们有 3 种方法,一种用于 List,一种用于 Set,一种用于 Map。

方法 1:使用toUnmodifiableList() 方法。假设我们有一个前 50 个偶数的 Stream 并从中创建一个不可变的 List。

例子:

Java

// 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 evenNumberStream
            = Stream.iterate(0, i -> i + 2).limit(50);
 
        // Creating List class object of integer tpye
        List evenNumbers
            = (List)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);
    }
}

输出:

方法二:使用 toUnmodifiableMap() 方法

考虑 Books 类的示例。 Books 对象有两个参数,即“Id”和“Name”。我们将生成一个书对象流。假设我们必须从这个对象集合中生成一个不可变的 Map。为此,我们使用 toUnmodifiableMap()函数。

例子:



Java

// 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 libInventory = new ArrayList();
 
        // 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 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");
    }
}

输出:

方法 3:使用 toUnmodifiableSet() 方法

实现:从流创建一个不可修改的 Set 来做到这一点,我们使用 toUnmodifiableSet()函数。

Java

// 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 randomDecimals
            = Stream.generate(Math::random).limit(30);
 
        // Now creating Set class object of type Double
        Set 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版本创建集合的不同方法。