Java12 Collectors.teeing you need to know about

Foreword

In Java 12, which has a very useful function but no official announcement of the JEP, because it is only in the Collector's a small change, its role is to merge the results of two collector, this sentence seems very abstract, the old rules, we first look at a map:

Pipeline reconstruction will often use this little thing, we usually call it "three links", its main role is to flow into and merge downstream1 downstream2, and then flows out of the merger

With the description of this image we get to the bar

Collectors.teeing

The above-mentioned feature is the small Collectors.teeing API, JDK first look at the note on the API, watching feel uncomfortable simply ignored, continue to look down examples like:

/**
 * Returns a {@code Collector} that is a composite of two downstream collectors.
 * Every element passed to the resulting collector is processed by both downstream
 * collectors, then their results are merged using the specified merge function
 * into the final result.
 *
 * <p>The resulting collector functions do the following:
 *
 * <ul>
 * <li>supplier: creates a result container that contains result containers
 * obtained by calling each collector's supplier
 * <li>accumulator: calls each collector's accumulator with its result container
 * and the input element
 * <li>combiner: calls each collector's combiner with two result containers
 * <li>finisher: calls each collector's finisher with its result container,
 * then calls the supplied merger and returns its result.
 * </ul>
 *
 * <p>The resulting collector is {@link Collector.Characteristics#UNORDERED} if both downstream
 * collectors are unordered and {@link Collector.Characteristics#CONCURRENT} if both downstream
 * collectors are concurrent.
 *
 * @param <T>         the type of the input elements
 * @param <R1>        the result type of the first collector
 * @param <R2>        the result type of the second collector
 * @param <R>         the final result type
 * @param downstream1 the first downstream collector
 * @param downstream2 the second downstream collector
 * @param merger      the function which merges two results into the single one
 * @return a {@code Collector} which aggregates the results of two supplied collectors.
 * @since 12
 */
public static <T, R1, R2, R>
Collector<T, ?, R> teeing(Collector<? super T, ?, R1> downstream1,
                          Collector<? super T, ?, R2> downstream2,
                          BiFunction<? super R1, ? super R2, R> merger) {
    return teeing0(downstream1, downstream2, merger);
}

API heavy sentence description is critical:

Every element passed to the resulting collector is
processed by both downstream collectors in conjunction with the "three links map" to illustrate that, each set is to be passed through the merger of the elements will downstream1 of processing and downstream2

Wherein the type of merger is BiFunction, that is receiving two parameters, and outputs a value, see its apply method

@FunctionalInterface
public interface BiFunction<T, U, R> {

    /**
     * Applies this function to the given arguments.
     *
     * @param t the first function argument
     * @param u the second function argument
     * @return the function result
     */
    R apply(T t, U u);
}

As to how you can deal with, we look at some examples of it

example

In order to better illustrate the use of teeing, citing four examples, read these four examples come back to look above the API, I believe you will be a way out

Counting and accumulating

First look at a classic problem, given a set of numbers, we need to map the integer number of elements and their flow and

class CountSum {
    private final Long count;
    private final Integer sum;
    public CountSum(Long count, Integer sum) {
        this.count = count;
        this.sum = sum;
    }

    @Override
    public String toString() {
        return "CountSum{" +
                "count=" + count +
                ", sum=" + sum +
                '}';
    }
}

By Collectors.teeing treatment

CountSum countsum = Stream.of(2, 11, 1, 5, 7, 8, 12)
        .collect(Collectors.teeing(
                counting(),
                summingInt(e -> e),
                CountSum::new));

System.out.println(countsum.toString());
  • A collection downstream1 counted by counting the static method Collectors
  • downstream2 collection element values ​​accumulated by the static method Collectors summingInt
  • merger results collected constructor CountSum

operation result:

CountSum{count=7, sum=46}

We get the results we want by teeing-time, continue to look at other examples down:

Maximum and minimum values

Given by the set one-time calculation of the maximum and minimum set, a new class the MinMax same, and is configured for creating the collection results merger

class MinMax {
    private final Integer min;
    private final Integer max;
    public MinMax(Integer min, Integer max) {
        this.min = min;
        this.max = max;
    }

    @Override
    public String toString() {
        return "MinMax{" +
                "min=" + min +
                ", max=" + max +
                '}';
    }
}

Calculation results teeing API:

MinMax minmax = Stream.of(2, 11, 1, 5, 7, 8, 12)
        .collect(Collectors.teeing(
                minBy(Comparator.naturalOrder()),
                maxBy(Comparator.naturalOrder()),
                (Optional<Integer> a, Optional<Integer> b) -> new MinMax(a.orElse(Integer.MIN_VALUE), b.orElse(Integer.MAX_VALUE))));

System.out.println(minmax.toString());
  • downstream1 minBy Collectors static method, the minimum is found in accordance with the natural ordering by Comparator comparator
  • downstream2 maxBy Collectors static method, the maximum is found in accordance with the natural ordering by Comparator comparator
  • merger results collected MinMax constructor, but to cope with the NPE, the two parameters through the BiFunction Optional Processing

operation result:

MinMax{min=1, max=12}

In order to verify Optional, we will add a set of null elements, and modify collation look sort the results:

MinMax minmax = Stream.of(null, 2, 11, 1, 5, 7, 8, 12)
                .collect(Collectors.teeing(
                        minBy(Comparator.nullsFirst(Comparator.naturalOrder())),
                        maxBy(Comparator.nullsLast(Comparator.naturalOrder())),
                        (Optional<Integer> a, Optional<Integer> b) -> new MinMax(a.orElse(Integer.MIN_VALUE), b.orElse(Integer.MAX_VALUE))));
  • downstream1 processing rule is null on the sort of front
  • downstream2 processing rule is null on the last sort of face
  • When the merger process, the method will be executed optional.orElse, minimum and maximum outputs

operation result:

MinMax{min=-2147483648, max=2147483647}

Melon and the total weight of the individual weight

For a next example is more fit the actual operation target

// 定义瓜的类型和重量
class Melon {
    private final String type;
    private final int weight;
    public Melon(String type, int weight) {
        this.type = type;
        this.weight = weight;
    }

    public String getType() {
        return type;
    }

    public int getWeight() {
        return weight;
    }
}

// 总重和单个重量列表
class WeightsAndTotal {
    private final int totalWeight;
    private final List<Integer> weights;
    public WeightsAndTotal(int totalWeight, List<Integer> weights) {
        this.totalWeight = totalWeight;
        this.weights = weights;
    }

    @Override
    public String toString() {
        return "WeightsAndTotal{" +
                "totalWeight=" + totalWeight +
                ", weights=" + weights +
                '}';
    }
}

And calculate the total weight of the single list by weight teeing API

List<Melon> melons = Arrays.asList(new Melon("Crenshaw", 1200),
    new Melon("Gac", 3000), new Melon("Hemi", 2600),
    new Melon("Hemi", 1600), new Melon("Gac", 1200),
    new Melon("Apollo", 2600), new Melon("Horned", 1700),
    new Melon("Gac", 3000), new Melon("Hemi", 2600)
);


WeightsAndTotal weightsAndTotal = melons.stream()
    .collect(Collectors.teeing(
            summingInt(Melon::getWeight),
            mapping(m -> m.getWeight(), toList()),
            WeightsAndTotal::new));

System.out.println(weightsAndTotal.toString());
  • Collectors downstream1 static method of cumulative weight do summingInt
  • downstream2 mapping the extracted melon wt Collectors static method and acquires the operation result by the end of toList stream ()
  • merger obtaining results WeightsAndTotal constructor

operation result:

WeightsAndTotal{totalWeight=19500, weights=[1200, 3000, 2600, 1600, 1200, 2600, 1700, 3000, 2600]}

An example of continuing co-paste it more practical:

The number of personnel appointments and appointments list

class Guest {
    private String name;
    private boolean participating;
    private Integer participantsNumber;

    public Guest(String name, boolean participating, Integer participantsNumber) {
        this.name = name;
        this.participating = participating;
        this.participantsNumber = participantsNumber;
    }
    public boolean isParticipating() {
        return participating;
    }

    public Integer getParticipantsNumber() {
        return participantsNumber;
    }

    public String getName() {
        return name;
    }
}

class EventParticipation {
    private List<String> guestNameList;
    private Integer totalNumberOfParticipants;

    public EventParticipation(List<String> guestNameList, Integer totalNumberOfParticipants) {
        this.guestNameList = guestNameList;
        this.totalNumberOfParticipants = totalNumberOfParticipants;
    }

    @Override
    public String toString() {
        return "EventParticipation { " +
                "guests = " + guestNameList +
                ", total number of participants = " + totalNumberOfParticipants +
                " }";
    }
}

By teeing API processing

var result = Stream.of(
                new Guest("Marco", true, 3),
                new Guest("David", false, 2),
                new Guest("Roger",true, 6))
                .collect(Collectors.teeing(
                        Collectors.filtering(Guest::isParticipating, Collectors.mapping(Guest::getName, Collectors.toList())),
                        Collectors.summingInt(Guest::getParticipantsNumber),
                        EventParticipation::new
                ));
System.out.println(result);
  • downstream1 filtered through a filtering method identified to participate in person and mapping out their names, and ultimately into toList collection
  • downstream2 counted by the method of accumulating summingInt
  • merger results collected constructor EventParticipation

Var result which we define to collect the results, did not specify the type, the syntactic sugar also speeds up the efficiency of our programming

operation result:

EventParticipation { guests = [Marco, Roger], total number of participants = 11 }

to sum up

In fact, teeing API is defined inside a static method Collectors flexible application will be processed by a collection of elements downstream1 and downstream2, eventually collected by the merger, when the project has collected simultaneously obtain two results, it is time to use up our teeing API

Soul questioning

  1. Collectors static method inside your application proficiency it?
  2. Project are you using JDK version is how much?
  3. Lambda skilled use of it?
  4. Your lights on it?

  1. Java Concurrency series of articles for the update
  2. Maven dependent thorough understanding transitive
  3. Excel also read with POI? Try this open source framework
  4. The basis of the interview, the interviewer always like to ask why the Java String

Welcome to continued public concern number: "arch day a soldier."

  • Dry cutting-edge Java technology sharing
  • Productivity tools summary | Reply "Tools"
  • Analysis of interview questions and answers
  • Technical Data collection | Reply "Information"

Easy to read detective novels thinking fun learning Java technology stack-related knowledge, in line with the simplification of complex issues, problems specific abstract and graphical decomposition of the principle of progressive technical issues, technology continues to update, please stay tuned ......


Guess you like

Origin www.cnblogs.com/FraserYu/p/11811242.html