Java核心技术:Java SE 8的流库——收集结果

收集结果

可以调用iterator方法,查看流中的元素。

Iterator<String> iterator = stream.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

可以调用forEach方法,将某个函数应用与每个元素

stream.forEach(System.out::println);

在并行流上,forEach方法会以任意顺序遍历各个元素。如果像按照流中顺序来处理,可以调用forEachOrdered方法。

stream.forEachOrdered(item -> System.out.println(item));

这个方法会丧失并行处理的部分甚至全部优势。


可以调用toArray,获得由流的元素构造的数组。stream.toArray()会返回一个Object[]数组。

Object[] objects = stream.toArray();

想要让数组具有正确的类型,可以将其传递到数组构造器中:

String[] array = stream.toArray(String[]::new);

针对将流中的元素收集到另一个目标中,可用collect方法,它接受一个Collector接口的实例。

List<String> list = stream.collect(Collectors.toList());
Set<String> set = stream.collect(Collectors.toSet());

要控制获得的集的种类,那么可以使用下面的调用:

ArrayList<String> arrayList = stream.collect(Collectors.toCollection(ArrayList::new));
TreeSet<String> treeSet = stream.collect(Collectors.toCollection(TreeSet::new));

想要通过链接操作来收集流中的所有字符串。可以调用:

String collect = stream.collect(Collectors.joining(","));

想要将流的结果约简为总和、平均值、最大值或最小值,可以使用summarizing(int|long|double)方法中的某一个。
这些方法会接受一个将流对象映射为数据的函数,同时,产生类型为(int|long|double)SummaryStatistic的结果,同时算总和、数量、平均值、最大值和最小值。

IntSummaryStatistics summaryStatistics = stream.collect(Collectors.summarizingInt(String::length));
 long sum = summaryStatistics.getSum();
 long count = summaryStatistics.getCount();
 summaryStatistics.getAverage();
 summaryStatistics.getMax();
 summaryStatistics.getMin();

收集结果——Stream
收集结果—Collectors
收集结果—SummaryStatics

收集到映射表中

Collectors.toMap方法用来将流中元素收集到一个映射表中。

Map<Integer, String> idToName = people.collect(Collectors.toMap(Person::getId, Person::getName));
Map<Integer, String> idToName = people.collect(Collectors.toMap(Person::getId, Function.identity()));
@FunctionalInterface
public interface Function<T, R> {
	/**
     * Returns a function that always returns its input argument.
     *
     * @param <T> the type of the input and output objects to the function
     * @return a function that always returns its input argument
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

如果有多个元素具有相同的键,那么就会存在冲突,收集器将抛出一个IllegalStateException对象。
可以通过提供第3个函数引元来覆盖这种行为,该函数会针对给定的已有值和新值来解决冲突并确定键对应的值。

Stream<Local> locales = Stream.of(Locale.getAvaliableLocales());
Map<String, String> languageNames = locales.collect(
	Collectors.toMap(
		Locale::getDisplayLanguage,
		l -> l.getDisplayLanguage(l),
		(existingValue, newValue) -> existingValue));

如果想要得到TreeMap,可以将构造器作为第4个引元来提供。且必须提供一个哈并函数。

Map<Integer, Person> idToPerson = people.collect(
	Collectors.toMap(
		Person::getId,
		Function.identity(),
		(existingValue, newValue) -> { throw new IllegalStateException(); }
		TreeMap::new));

对于每个toMap方法,都有一个等价的可以产生并发映射表的toConcurrentMap方法。
收集到映射表—Collectors

群组和分区

groupingBy方法支持将具有相同特性的值群聚成组。

Map<String, List<Locale>> countryToLocales = locales.collect(
	Collectors.groupingBy(Locale::getCountry));
List<Locale> swissLocales = countryToLocales.get("CH");

当分类函数是断言函数(即返回boolean值的函数)时,流的元素别分为两个列表:该函数返回true的元素和其他元素。这种情况下,使用partitioningBy比使用groupingBy要更高效。

Map<Boolea, List<Locale>> englishAndOtherLocales = locales.collect(
	Collectors.partitionBy(l -> l.getLanguage().equals("en");

分组—Collector

下游收集器

groupingBy方法会产生一个映射表,它的每个值都是一个列表。想要以某种方式来处理这些列表,就需要提供一个“下游收集器”。

Map<String, Set<Locale>> countryToLocaleSet = locales.collect(
	groupingBy(Locale::getCountry, Collector.toSet();

Java提供了多种可以将群组元素约简为数字的收集器:

Map<String, Long> countryToLocaleCounts = locales.collect(
	groupingBy(Locale::getCountry, counting());
Map<String, Integer> stateToCityPopulation = cities.collect(
	groupingBy(City::getState, summingInt(City::getPopulation)));
Map<String, Optional<City>> stateToLargestCity = cities.collect(
	groupingBy(City::getState, maxBy(Comparator.comparing(City::getPopulation))));
Map<String, Optional<String>> stateToLongestCityName = cities.collect(
	groupingBy(City::getState, mapping(City::getName, maxBy(Comparator.comparing(String::length)))));
Map<String, Set<String>> countryToLanguages = locales.collect(
	groupingBy(Locale::getDisplayCountry, mapping(Locale::getDisplayLanguage, toSet())));
Map<String, IntSummaryStatistics> stateToCityPopulationSummary = cities.collect(groupingBy(City::getState, summarizingInt(City::getPopulation)));

下游收集器—Collector

约简操作

reduce方法是一种用于从流中计算某个值的通用机制,其最简单形式将接受一个二元函数,并从前两个元素开始持续应用它。

List<Integer> values = ...;
Optional<Integer> sum = values.strema().reduce(((x, y) -> x + y);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值