У меня есть это упражнение:
List<Integer> iList = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
Predicate<Integer> p = x -> x%2 == 0;
List newList = iList.stream()
.filter(p)
.filter(x -> x>3)
.collect(Collectors.toList());
System.out.println(newList);
На мой взгляд, newList является необработанным, а не универсальным типом, потому что он был инициализирован как List newList, а не как List<Integer>.
Как можно получить нормальный результат для этого упражнения, а не ошибку компиляции?
Если я напишу:
List iList = Arrays.asList(1,2,3,4,5,6,7);
iList.stream()
.filter(x -> x%2==0)
.filter(x -> x>3)
.collect(Collectors.toList());
Он не компилируется. Почему в первом случае код компилируется?
Второй фрагмент не компилируется из-за простой опечатки. И идея о том, что необработанные типы приводят к ошибке компиляции (по умолчанию), просто неверна.




Вы правы, это необработанный тип:
List newList = iList.stream().filter(p).filter(x>x>3).collect(Collectors.toList());
System.out.println(newList);
Однако необработанные типы вполне допустимы и не вызовут ошибки компиляции. Они просто очень плохая практика для использования. Это демонстрируется вашим вторым фрагментом кода:
List iList= Arrays.asList(1,2,3,4,5,6,7);
iList.stream().filter(x -> x%2 ==0).filter(x -> x>3).collect(Collectors.toList());
Здесь, поскольку iList является необработанным типом, компилятор не знает, что iList содержит int, и обрабатывает их как объекты, поэтому вы не можете использовать здесь оператор %. Фактическая ошибка, которую я получаю:
bad operand types for binary operator '%'
first type: Object
second type: int
bad operand types for binary operator '>'
first type: Object
second type: int
Note that this is ignoring your syntax error in your lambdas. The correct syntax is x -> x > 3 and not x>x>3
Но почему код компилируется в первом случае и не компилируется во втором?
@Adryr83 Adryr83 Поскольку компилятор обрабатывает содержимое как Object, поэтому вы не можете использовать для них % или >
Я использовал одни и те же методы в обоих случаях. Я знаю, что с необработанным типом я должен использовать только методы объекта. Но почему в первом случае компилятор компилирует? У меня должна быть ошибка компиляции в обоих случаях.
@ Adryr83 Почему? Вы можете получить List<Object>. Ошибка возникает, когда вы пытаетесь использовать List<Object> как List<Integer>
Да, но и в первом случае у меня есть List<Object> с именем newList. В первом случае только iList является универсальным типом, а не newList.
@ Adryr83 Только newList здесь необработанный тип. Единственное, что вы делаете с этим, это распечатываете его, что действительно для List<Object>
Хорошее объяснение @GBlodgett
Stream распознает последовательность необработанных объектов как простой Stream<Object>. Если вы хотите рассматривать это как Stream<Integer>, вы должны явно объявить этот факт, используя Stream::mapToInt и упаковав все Stream:
List<Integer> newList = iList.stream() // Stream
.mapToInt(obj -> Integer.valueOf(obj.toString())) // IntStream
.boxed() // Stream<Integer>
.filter(x -> x % 2 == 0)
.filter(x -> x > 3)
.collect(Collectors.toList()); // List<Integer>
В первом случае очевидно, что Stream объявляет себя Stream<Integer>, поскольку он создан из List<Integer>.
Note you have the wrong syntax of the lambda which should be x -> x % 2 == 0 with an arrow ->.
List newList — это просто возвращаемый тип цепочки потоков.
На самом деле вы работаете с List<Integer> iList, который НЕ является необработанным типом. Поэтому нет ошибки компиляции
Необработанные типы совершенно законны, но очень плохая практика, о чем свидетельствует ваш второй фрагмент кода, который не компилируется.