2014-12-19 4 views
5

В коллекции Scala представлен метод collect, который объединяет filter и map в один метод. Это особенно полезно при фильтрации коллекции Object для создания подмножества этой коллекции, содержащей только определенный тип.Есть ли метод потока Java, эквивалентный коллекциям Scala «собирать»?

Есть ли такая вещь с потоком Java 8?

+1

Я полагаю, вы уже знаете, что можете поступать правильно, цепляя вызовы 'map',' filter' и 'collect'. Итак, какова цель вашего запроса сделать это в одном вызове метода? Потому что «чувствует», как быть более эффективным? – Holger

+0

@Holger Он связывает предварительное условие с функцией сопоставления, что помогает сделать очевидным одно предварительное условие для другого, а также сделать невозможным разорвать код, изменив порядок вызовов метода. –

+3

Собственно, все наоборот. Никто не может сказать по сигнатуре одного метода, содержащей функцию сопоставления и предикат, который применяется первым. Напротив, с API «Stream» каждый понимает разницу между «map (...) .filter (...) .collect (...)» и «.filter (...) .map (...) .collect (...)'. И даже способен вывести значение других комбинаций, таких как 'map (...) .filter (...) .map (...) .collect (...)' ... – Holger

ответ

7

Имея комбинацию filter и map в одном шаге не то, что полезно в Java учитывая его тип системы. Например. такого типа PartialFunction.

Ближайший вещь flatMap:

List<Object> list=Arrays.asList(0, "foo", 0L, 42.0, true, "false"); 
List<String> sList = list.stream() 
    .flatMap(o-> o instanceof String? Stream.of((String)o): Stream.empty()) 
    .collect(Collectors.toList()); 
System.out.println(sList); 

но выразительность

.flatMap(o-> o instanceof String? Stream.of((String)o): Stream.empty()) 

не то, что больше по сравнению с

.filter(o -> o instanceof String).map(o -> (String)o) 

Конечно, вы можете создать вспомогательный метод инкапсулируя эти шаги в единую неразрывную операцию:

static <T> Stream<T> onlyType(Stream<?> s, Class<T> type) { 
    return s.filter(type::isInstance).map(type::cast); 
} 

, то вы можете использовать его как

List<String> sList=onlyType(list.stream(), String.class).collect(Collectors.toList()); 
0

Я пытаюсь дать ответ на ваш вопрос, как я где-то читал -

<R,A> R collect(Collector<? super T,A,R> collector) 

R - тип результата А - промежуточный тип накопления коллектора коллектора - Коллектор описывающее уменьшение Возврат - результат восстановления

Выполняет изменчивую операцию сокращения элементов этого потока с использованием коллектора. Коллекционер инкапсулирует функции, используемые в качестве аргументов для сбора (Поставщик, BiConsumer, BiConsumer), позволяющий повторно использовать стратегии сбора и составные операции сбора, такие как группировка или разбиение на несколько уровней. Если поток параллелен, а коллектор является параллельным, и либо поток неупорядочен, либо коллектор неупорядочен, то будет выполняться параллельное восстановление (см. «Коллектор» для получения подробной информации о параллельном восстановлении.)

Это терминал операция.

При параллельном выполнении несколько промежуточных результатов могут быть созданы, заполнены и объединены, чтобы поддерживать изоляцию изменяемых структур данных. Поэтому даже при параллельном выполнении с не-потокобезопасными структурами данных (такими как ArrayList) дополнительная синхронизация не требуется для параллельной редукции.

Ниже будут накапливаться строки в ArrayList:

List<String> asList = stringStream.collect(Collectors.toList()); 

Ниже будет классифицировать объекты Person государством и городом, каскадный два коллектора вместе:

Map<String, Map<String, List<Person>>> peopleByStateAndCity 
    = personStream.collect(Collectors.groupingBy(Person::getState, 
                Collectors.groupingBy(Person::getCity))); 
+0

Я не говорю о методе 'collect' для Java' S''. Я говорю о методе «собирать» Scala и запрашиваю эквивалент в Java 8. –

0

Насколько я могу сказать от интерфейс Stream и некоторые поддерживающие библиотеки, нет операции, которая выполняет обе эти операции и производит вывод Stream (на основе моего короткого чтения г метода Scala collect).

Вам необходимо применить обе функции к Stream, чтобы получить желаемый результат Stream, который затем может быть собран или любые другие функции, которые вы хотите применить к нему.

collection.stream() 
    .filter(predicateFunction) 
    .map(mappingFunction) 
    .collect(Collectors.toList()) 
+1

Это * - это одна операция, но эта операция выполняется с помощью цепочки вызовов метода, которая просто повышает гибкость API. – Holger

0

Как я понимаю, в документации Scala, collect фильтров в зависимости от того, присутствует функцию, и применяет функцию к каждому отборочному объекту. Класс Java имеет фиксированное определение, поэтому такой тест не имеет большого смысла. Наиболее близким аналогом будет испытывать для интерфейса и вызова его метода (функция) в несколько стадий:

stream.filter(e -> e instanceof SomeInterface).map(SomeInterface.class::cast).map(AnotherClass::convertSomeInterfaceToSomethingElse) 
0

Попробуйте как этот

tList.stream().map[E](func).collect(Collectors.toList[E]) 

TList является типом вас список источников, и Е представляет собой тип, который Вы хотите returned.If тип источника такой же, как и возвращаемый тип, [E] не требуется в mapE, кажется, что функция func в scala возвращает тип - это объект.

Смежные вопросы