collect
должен сказать даStream
Самая мощная из терминальных операций, и ее использование может быть практически произвольной агрегацией данных, которую вы хотите, и хороший анализ использования инструмента ниже.
В интерфейсе Stream есть два метода:
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
<R, A> R collect(Collector<? super T, A, R> collector);
Очевидно, что первый эквивалентен простому варианту реализации, а второй — расширенному использованию.Все более сложные операции инкапсулируются в интерфейс Коллектора, а также предоставляются некоторые статические методы для вызова пользователями.Следующий анализ проводится один раз. одним.
Простая форма звонка
Простая форма вызова - это первый интерфейс, интерфейс выглядит следующим образом
<R> R collect(Supplier<R> supplier,
BiConsumer<R, ? super T> accumulator,
BiConsumer<R, R> combiner);
Метод вызова следующий, очевидно, первый параметрsupplier
Контейнер для результата, второй параметрaccumulator
Операция добавления результата в контейнер, третий параметрcombiner
Это стратегия агрегации нескольких контейнеров.
String concat = stringStream.collect(StringBuilder::new, StringBuilder::append,StringBuilder::append).toString();
//等价于上面,这样看起来应该更加清晰
String concat = stringStream.collect(() -> new StringBuilder(),(l, x) -> l.append(x), (r1, r2) -> r1.append(r2)).toString();
Потом по-другому, я хочу собрать сумму результатов для List.Согласно требованиям Collect, нам сначала нужна сумма контейнера, а затем добавить операцию sum+x, операцию агрегации, sum1+sum2, затем легко написать, прочитав следующий код После хорошего опыта, а затем посмотрите на расширенное использование.Конечно, использование метода суммы для сбора является лучшим решением, вот только пример приложения.
// 由于基本类型都是不可变类型,所以这里用数组当做容器
final Integer[] integers = Lists.newArrayList(1, 2, 3, 4, 5)
.stream()
.collect(() -> new Integer[]{0}, (a, x) -> a[0] += x, (a1, a2) -> a1[0] += a2[0]);
Итак, вернемся к одному изPerson
класс, который имеет два атрибута, тип и имя, затем используйтеcollect
Соберите его в коллекцию Map, где ключ — тип, а значение — коллекция person Как показано в следующем коде, вы можете понять метод, когда увидите его, и поверите ему.
Lists.<Person>newArrayList().stream()
.collect(() -> new HashMap<Integer,List<Person>>(),
(h, x) -> {
List<Person> value = h.getOrDefault(x.getType(), Lists.newArrayList());
value.add(x);
h.put(x.getType(), value);
},
HashMap::putAll
);
Collector Advanced Call.
Collector
Интерфейс должен сделатьcollect
Мощное действующее абсолютное оружие для большинства операций можно разбить на основные этапы,Предоставление начального контейнера -> добавление элементов в контейнер -> агрегация нескольких контейнеров при одновременном выполнении -> работа с агрегированными результатами,в то же времяCollector
Интерфейс также обеспечиваетof
Статические методы помогут вам настроить ваши операции в наибольшей степени, а официальный также предоставляетCollectors
Этот вид упаковки наиболее распространен при инкассаторских операциях.
Кроме тогоCollectorImpl
заCollector
Класс реализации, поскольку интерфейс не может быть создан, операция создания экземпляра в основном завершается здесь.
//初始容器
Supplier<A> supplier();
//加入到容器操作
BiConsumer<A, T> accumulator();
//多容器聚合操作
BinaryOperator<A> combiner();
//聚合后的结果操作
Function<A, R> finisher();
//操作中便于优化的状态字段
Set<Characteristics> characteristics();
Метод инкапсуляции коллекторов
Collectors
В качестве официального класса инструмента коллекции многие из его операций носят справочный характер, что может помочь нам лучше понятьCollector
Интерфейс неотделим от своей оригинальности, в конце концов, это просто смешанная работа пяти вышеперечисленных функциональных интерфейсов, давайте проанализируем, как чиновник использует эти интерфейсы.
toList()
контейнер:ArrayList::new
Добавленные контейнерные операции:List::add
Слияние нескольких контейнеров:left.addAll(right); return left;
Операция результата после агрегации: возвращается непосредственно здесь, поэтому такой операции нет, по умолчаниюcastingIdentity()
Поле состояния операции оптимизации:CH_ID
Выглядит это очень просто, поэтому для Map, Set и других операций аналогичны реализации.
public static <T>
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
joining()
контейнер:StringBuilder::new
Присоединиться к контейнерной операции:StringBuilder::append
Слияние нескольких контейнеров:r1.append(r2); return r1;
Результат операции после агрегации:StringBuilder::toString
Поле состояния операции оптимизации:CH_NOID
public static Collector<CharSequence, ?, String> joining() {
return new CollectorImpl<CharSequence, StringBuilder, String>(
StringBuilder::new, StringBuilder::append,
(r1, r2) -> { r1.append(r2); return r1; },
StringBuilder::toString, CH_NOID);
}
Вот сложный
groupingBy()
groupingBy
даtoMap
продвинутый способ макияжаtoMap
Разнообразные операции сбора не могут быть предоставлены для значений, таких как возвратMap<T,List<E>>
такая формаtoMap
Тогда это не тоgroupingBy
Основное внимание уделяется обработке и инкапсуляции значений Key и Value. Проанализируйте следующий код, гдеclassifier
это обработка ключевого значения,mapFactory
Он указан для указания конкретного типа контейнера для MAP.downstream
Для работы сбора ценности конкретный код не проанализирован здесь, не более, чем в указанный контейнер.
public static <T, K, D, A, M extends Map<K, D>>
Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
Supplier<M> mapFactory,
Collector<? super T, A, D> downstream) {
.......
}
Для девственницы передcollect
Работа сбора, выполненная методом, может быть легко переписана в качестве формы групповой группы
//原生形式
Lists.<Person>newArrayList().stream()
.collect(() -> new HashMap<Integer,List<Person>>(),
(h, x) -> {
List<Person> value = h.getOrDefault(x.getType(), Lists.newArrayList());
value.add(x);
h.put(x.getType(), value);
},
HashMap::putAll
);
//groupBy形式
Lists.<Person>newArrayList().stream()
.collect(Collectors.groupingBy(Person::getType, HashMap::new, Collectors.toList()));
//因为对值有了操作,因此我可以更加灵活的对值进行转换
Lists.<Person>newArrayList().stream()
.collect(Collectors.groupingBy(Person::getType, HashMap::new, Collectors.mapping(Person::getName,Collectors.toSet())));
reducing()
reducing
Это коллекция для одного значения, и ее возвращаемый результат является не типом семейства коллекций, а одним классом сущностей T.
контейнер:boxSupplier(identity)
Здесь завернута длина массива Object 1 [] , по причинам природы это неизменяемый тип pot
Присоединиться к контейнерной операции:a[0] = op.apply(a[0], t)
Слияние нескольких контейнеров:a[0] = op.apply(a[0], b[0]); return a;
Операция результата после агрегации: результатом, естественно, являются данные, обернутые Object[0]a -> a[0]
Поле состояния операции оптимизации:CH_NOID
Итак, когда я вижу здесь замешательство, есть ли у меня чувство внезапного осознания?
public static <T> Collector<T, ?, T>
reducing(T identity, BinaryOperator<T> op) {
return new CollectorImpl<>(
boxSupplier(identity),
(a, t) -> { a[0] = op.apply(a[0], t); },
(a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
a -> a[0],
CH_NOID);
}
Затем следующим шагом является преобразование некоторых операций из предыдущей команды Collect.
//原生操作
final Integer[] integers = Lists.newArrayList(1, 2, 3, 4, 5)
.stream()
.collect(() -> new Integer[]{0}, (a, x) -> a[0] += x, (a1, a2) -> a1[0] += a2[0]);
//reducing操作
final Integer collect = Lists.newArrayList(1, 2, 3, 4, 5)
.stream()
.collect(Collectors.reducing(0, Integer::sum));
//当然Stream也提供了reduce操作
final Integer collect = Lists.newArrayList(1, 2, 3, 4, 5)
.stream().reduce(0, Integer::sum)
возможные проблемы
Запишите некоторые незначительные ошибки, возникшие при использовании инструмента в производственной среде.
исключение, сгенерированное toMap
Работа toMap в основном выглядит следующим образом, за исключением двух аспектов.
- Действие называется
map.merge
метод, этот метод будет сообщать npe, когда значение равно нулю, даже если вы используете hashMap, который может принимать нулевые значения, он все равно будет сообщать Я не понимаю, почему это разработано здесь. - Стратегия слияния конфликта не указана, что является третьим параметром
BinaryOperator<U> mergeFunction
Когда встречается дубликат ключа, он будет выброшен напрямуюIllegalStateException
Так что вам нужно обратить внимание.
Суммировать
до сих пор дляcollect
Операция должна быть очень ясной, я надеюсь понять суть этих примеров, то естьCollector
Роль этих функций в интерфейсе, надеюсь, вам поможет.
личный блогmrdear.cn, добро пожаловать на обмен