Тип стирания в потоках - PullRequest
0 голосов
/ 04 июня 2019

Я не новичок в Java 8, и я знаю, что потоки являются очень мощным и удобным способом обработки данных, и я использую их очень часто.На самом деле я делал намного более сложную обработку данных с потоками без каких-либо проблем, но посмотрите на это?Это выглядит как базовая обработка, но есть проблема с стиранием типов.Почему он не может справиться с таким сбором данных?

Set[] arrOfSets = {new TreeSet<>(List.of(1, 2)), new LinkedHashSet<>(Arrays.asList(1, 2, 3, null))};

/*why type erasure wins here? */
List<Number> collect = (List<Number>) Arrays.stream(arrOfSets).flatMap(Set::Stream).collect(Collectors.toList());

Object collect2 = Arrays.stream(arrOfSets).flatMap(set -> set.stream()).collect(Collectors.toList());
System.out.println("Collect2:" + collect2); /*[1, 2, 1, 2, 3, null]*/

/*Here type interference works fine*/
List<Integer> collect1 = new TreeSet<>(Arrays.asList(1, 2, 3)).stream().collect(Collectors.toList());

System.out.println(collect2.getClass().getSimpleName()); //ArrayList

То же самое с List<Set>:

List<?> collect3 = listOfSets.stream().flatMap(Set::stream).collect(Collectors.toList());

Исключение во время выполнения: java: несовместимые типы: java.lang.Object не может быть преобразован в java.util.List

Я чувствую, что это огромный недостаток потоков.Есть ли шансы улучшить помехи типа в Streams API в будущем SDK или нет способа преодолеть эту проблему?

1 Ответ

1 голос
/ 04 июня 2019

Проблема в том, что вы используете необработанный Set[] без универсального типа.

Чтобы ваш код работал, вы должны либо использовать универсальный массив:

Set<Number>[] arrOfSets = new Set[]{
        new TreeSet<>(List.of(1, 2)), 
        new LinkedHashSet<>(Arrays.asList(1, 2, 3, null))
};
List<Number> collect = Arrays.stream(arrOfSets) // Stream<Set<Number>>
        .flatMap(Set::stream) // Stream<Number>
        .collect(Collectors.toList());

, либо приведениеваш поток от Stream<Object> до Stream<Number> с использованием Stream.map():

Set[] arrOfSets = new Set[]{
        new TreeSet<>(List.of(1, 2)), 
        new LinkedHashSet<>(Arrays.asList(1, 2, 3, null))
};
List<Number> collect = Arrays.stream(arrOfSets) // Stream<Set>
        .map(i -> (Set<Number>) i) // Stream<Set<Number>>
        .flatMap(Set::stream) // Stream<Object>
        .collect(Collectors.toList());

Как вы уже упоминали, проблема такая же для List<Set>Set нет типа, поэтому либо используйте List<Set<Number>>, либо приведите, как раньше. Я бы порекомендовал использовать набранные List s или Set s.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...