📜  Java收集器

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

Java收集器

Collectors是 JDK 中的实用类之一,它包含许多实用功能。它主要与 Stream API 一起使用,作为最后一步。在本文中,我们将研究收集器类中的不同方法。

当谈到Java编程的函数式风格时,我们通常很少使用我们广泛使用的函数,这些函数是属于 Streams API 的filter()map()reduce()collect()collect()reduce()方法被称为终端方法,因为在这里,操作会因某些结果而终止。与收集器关联的函数通常在 collect() 方法中使用。 Collectors 类是 Stream 包的一部分,可以导入为:

import static java.util.stream.Collectors.*;

类层次结构:

java.lang.Object
    ↳ java.util.stream
        ↳ class Collectors

句法:

public final
  class Collectors
    extends Object

Collectors 类中的方法

让我们考虑一个City类,它具有使用参数化构造函数初始化的名称温度等属性。我们将使用此示例观察收集器类中可用的不同方法。

下面是 City 类的实现:

// Java program to implement a
// City class
  
// Defining a city class
public class City {
  
    // Initializing the properties
    // of the city class
    private String name;
    private double temperature;
  
    // Parameterized constructor to
    // initialize the city class
    public City(String name, double temperature)
    {
        this.name = name;
        this.temperature = temperature;
    }
  
    // Getters to get the name and
    // temperature
    public String getName()
    {
        return name;
    }
  
    public Double getTemperature()
    {
        return temperature;
    }
  
    // Overriding the toString method
    // to return the name and temperature
    @Override
    public String toString()
    {
        return name + " --> " + temperature;
    }
}

在进入不同的方法之前,让我们创建一个带有名称和温度的城市列表。下面是创建带有名称和温度的城市列表的方法的实现:

// Java program to create a list
// of cities with name and
// temperature
  
// Function to create a list of
// cities with name and temperature
private static List prepareTemperature()
{
    List cities = new ArrayList<>();
    cities.add(new City("New Delhi", 33.5));
    cities.add(new City("Mexico", 14));
    cities.add(new City("New York", 13));
    cities.add(new City("Dubai", 43));
    cities.add(new City("London", 15));
    cities.add(new City("Alaska", 1));
    cities.add(new City("Kolkata", 30));
    cities.add(new City("Sydney", 11));
    cities.add(new City("Mexico", 14));
    cities.add(new City("Dubai", 43));
    return cities;
}

以下是对上述城市进行操作的各种方法:

1. Collector> toList():将输入元素转化为新的List,返回一个Collector。这里, T是输入元素的类型。在下面的示例中,我们试图处理温度超过 10 的城市列表,并且只获取城市名称。

为此,我们使用filter()应用温度的过滤检查,我们使用map()转换城市名称并使用collect()收集这些城市名称。现在这个collect()方法基本上用于收集通过流及其各种函数传递的元素并返回一个 List 实例。

// Java program to implement the 
// toList() method 
import java.util.ArrayList; 
import java.util.List; 
import java.util.stream.Collectors; 
    
public class GFG { 
    
    public static void main(String[] args) 
    { 
    
        // The following statement filters 
        // cities having temp > 10 
        // The map function transforms only 
        // the names of the cities 
        // The collect function collects the 
        // output as a List 
        System.out.println(prepareTemperature().stream()
                 .filter(f -> f.getTemperature() > 10)
                 .map(f -> f.getName())
                 .collect(Collectors.toList())); 
    } 
} 

输出:

Java 中的收集器示例

在这里,输出中不存在阿拉斯加城市,因为它的温度被初始化为 1。

2. Collector> toSet():将输入元素转化为新的Set,返回一个Collector。此方法将返回 Set 实例,并且不包含任何重复项。

// Java program to implement the
// toSet() method
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
   
        // Here, we have applied the filter
        // to get the set of the names
        // of the cities whose temperature
        // is greater than 10
        System.out.println(prepareTemperature()
                .stream()
                .filter(f -> f.getTemperature() > 10)
                .map(f -> f.getName())
                .collect(Collectors.toSet()));
        }
}

输出:

在这里,我们可以注意到输出中没有重复墨西哥和迪拜。

3. Collector toCollection(Supplier collectionFactory):将输入元素转化为新的Collection,返回一个Collector。如果我们观察上面讨论的 toList() 和 toSet() 方法,我们无法控制它们的实现。因此,使用 toCollection() 我们可以实现自定义实现,其中 C 是结果集合的类型,T 是输入元素的类型。

// Java program to implement the
// toCollection() method
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
   
        // Here, a list of all the names
        // have been returned
        System.out.println(prepareTemperature()
                .stream()
                .map(f -> f.getName())
                .collect(Collectors.toCollection(List::new)));
    }
}

输出:

同样,我们可以使用所有其他的实现类,如 ArrayList、HashSet、TreeSet 等。

4. Collector> toMap(函数 keyMapper, 函数 valueMapper):将元素转换为Map,其键和值是对输入元素应用传入的mapper函数的结果,并返回一个集电极。 toMap() 用于收集元素的输入并将其转换为 Map 实例。 toMap() 方法要求以下参数:

K - Key function
U - Value Function
BinaryOperator(optional)
Supplier(Optional)

让我们尝试通过一个例子来理解这一点。对于上面讨论的城市和温度列表,我们想在地图中获取城市名称和温度。

如果列表没有重复项,则上述语句完美运行。由于我们的列表包含重复项,因此它不会像 toSet() 那样默默地过滤掉它。相反,它会引发 IllegalStateException。我们可以通过避免与第三个参数 BinaryOperator 发生键冲突(在重复键的情况下)来避免和解决此问题。例如:

// Java program to implement the
// Map() method
   
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
        // Here, the name and the temperature
        // are defined as the type City
        System.out.println(prepareTemperature()
                .stream()
                .filter(city -> city.getTemperature() > 10)
                .collect(Collectors.toMap(
                            City::getName,
                            City::getTemperature,
                            (key, identicalKey) -> key)));
    }
}

输出:

二元运算符指定,我们如何处理碰撞。上面的语句选择了任何一个冲突元素。

5、CollectorcollectingAndThen(Collectordownstream, 函数 ):这个方法可以让我们在收集collection的输入元素后,对结果进行另外的操作。

// Java program to implement the
// collectingAndThen() method
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
        // Collects the elements and
        // counts the occurrences
        System.out.println(prepareTemperature()
                .stream()
                .collect(Collectors.groupingBy(
                            City::getName,
                            Collectors.collectingAndThen(
                                    Collectors.counting(),
                                    f -> f.intValue()))));
    }
}

输出:

6. Collectorcounting():统计T类型的输入元素个数,返回一个Collector。此方法用于我们想要分组并计算每个城市出现在元素集合中的次数的情况。

// Java program to implement the
// counting() method
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
        System.out.println(prepareTemperature()
                .stream()
                .collect(Collectors.groupingBy(
                            City::getName,
                            Collectors.counting())));
    }
}

输出:

我们可以看到墨西哥和迪拜这两个城市计数为2,其余的都可用一次。而且, groupingBy 的返回类型是Map

7. Collector > groupingBy(函数 classifier):对T类型的输入元素进行分组操作。元素的分组按照传递的分类器函数完成,并返回带有结果的Collector在地图中。

// Java program to implement the
// groupingBy() method
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
        System.out.println(prepareTemperature()
                .stream()
                .collect(Collectors.groupingBy(City::getName)));
    }
}

输出:

在上面的例子中,像墨西哥和迪拜这样的城市已经被分组,其余的组只包含一个城市,因为它们都是单独的。上述 groupingBy() 的返回类型是Map

8. Collector groupingBy(函数 classifier, Collector下游):对T类型的输入元素进行分组操作。元素的分组按照传递的分类器函数进行,然后对元素进行归约操作根据指定的下游收集器与给定键关联的值,并在 Map 中返回具有结果的收集器。

9. Collector groupingBy(函数 classifier, Supplier mapFactory, Collector下游):对类型T的输入元素进行分组操作,元素的分组按照传递的分类器函数完成,然后对与a关联的值执行归约操作根据指定的下游收集器给定键并返回收集器。

10. Collectorjoining():将输入元素拼接成一个String,返回一个Collector。

11、收集器加入(CharSequence delimiter):连接输入元素,用指定的分隔符分隔,返回一个收集器。

// Java program to implement the
// joining() method
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
        // Concatenate the collection with
        // comma
        System.out.println(prepareTemperature()
                .stream()
                .filter(city -> city.getTemperature() > 10)
                .map(f -> f.getName())
                .collect(Collectors.joining(", ")));
    }
}

输出:

12. Collector join(CharSequence delimiter, CharSequence prefix, CharSequence suffix):按照指定的前缀和后缀连接输入元素,由指定的分隔符分隔,并返回一个收集器。

// Java program to implement the
// joining() method
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
        System.out.println(prepareTemperature()
                .stream()
                .filter(city -> city.getTemperature() > 10)
                .map(f -> f.getName())
                .collect(Collectors.joining(" ", 
                "Prefix:", ":Suffix")));
    }
}

输出:

13.收集器映射(函数映射器,下游收集器):通过将映射函数应用于转换之前的每个输入元素,将类型为 U 的输入元素的收集器转换为类型为 T 的输入元素。

// Java program to implement the
// mapping() method
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
        System.out.println(prepareTemperature()
                .stream()
                .collect(Collectors.groupingBy(
                            City::getName,
                            Collectors.mapping(
                                City::getTemperature,
                                Collectors.toList()))));
    }
}

输出:

在上面的输出中,每个城市组只包含温度,这是在
mapping()方法,它接受两个函数参数类型的函数和收集器。上面的映射方法返回一个列表,最后上面的 groupingBy() 方法的返回类型变成了Map 。我们还可以使用 toSet() 方法来获取元素集合而不是列表,如下所示:

// Java program to implement the
// joining() method
   
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
        System.out.println(prepareTemperature()
                .stream()
                .collect(Collectors.groupingBy(
                            City::getName,
                            Collectors.mapping(
                                    City::getTemperature,
                                    Collectors.toSet()))));
    }
}

输出:

如果我们观察输出并将其与前一个输出进行比较,则重复项已被删除,因为它现在是一个集合。上述 groupingBy() 的返回类型现在变为Map

14. Collector> partitioningBy(Predicate predicate):根据传入的Predicate对输入元素进行分区,并将其转化为Map并返回Collector。

// Java program to implement the
// partitioningBy() method
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
   
public class GFG {
   
    public static void main(String[] args)
    {
        // Here, we are partitioning the list
        // in two groups i.e., Cities having
        // temperatures more than 15
        // and other than that.
        System.out.println(prepareTemperature()
                .stream()
                .collect(Collectors.partitioningBy(
                            city -> city.getTemperature() > 15)));
    }
}

输出:

15. Collector partitioningBy(Predicate predicate, Collector下游):根据传入的Predicate对输入元素进行分区,并按照另一个Collector收集每个分区的值,并将其转换为Map,其值为下游归约和然后返回收集器。

16. Collector averagingDouble(ToDoubleFunction mapper):对Double类型的输入元素进行平均,并返回Collector作为结果。

17. Collector averagingInt(ToIntFunction mapper):对Int类型的输入元素进行平均,并返回Collector作为结果。

18. Collector averagingLong(ToLongFunction mapper):对Long类型的输入元素进行平均,并返回Collector作为结果。

19. Collector> groupingByConcurrent(函数 classifier):对T类型的输入元素进行分组操作,根据传入的分类器函数对元素进行分组,返回并发Collector。

20. Collector groupingByConcurrent(函数 classifier, Collectordownstream):对T类型的输入元素进行分组操作,按照传入的分类器函数进行元素的分组,然后进行归约操作根据指定的下游收集器在与给定键关联的值上,并返回并发收集器。

21. Collector groupingByConcurrent(函数 classifier, Supplier mapFactory, Collectordownstream):对T类型的输入元素进行分组操作,根据传入的分类器函数对元素进行分组,然后对关联的值进行归约操作根据指定的下游收集器的给定键并返回并发收集器。

22. Collector reduction(BinaryOperator op):根据传递的 BinaryOperator 对其输入元素进行归约,并返回一个 Collector。

23. Collector reduction(T identity, BinaryOperator op):根据传递的 BinaryOperator 和传递的标识执行其输入元素的归约并返回 Collector。

24. Collector maxBy(Comparator compare):根据给定的 Comparator 产生最大元素,返回一个 Optional Collector。

25. Collector minBy(Comparator compare):根据给定的 Comparator 生成最小元素,返回 Optional Collector。

26. Collector toConcurrentMap(函数 keyMapper, 函数 valueMapper) :将元素转换为ConcurrentMap,其键和值是传递给输入元素的mapper函数的结果,并返回一个并发Collector。

参考: https: Java/util/stream/Collectors.html