Этот код работает (взят из Javadoc):
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
String commaSeparatedNumbers = numbers.stream()
.map(i -> i.toString())
.collect(Collectors.joining(", "));
Этот не может быть скомпилирован:
int[] numbers = {1, 2, 3, 4};
String commaSeparatedNumbers = Arrays.stream(numbers)
.map((Integer i) -> i.toString())
.collect(Collectors.joining(", "));
IDEA сообщает мне, что у меня есть «несовместимый тип возвращаемого значения String в лямбда-выражении».
Зачем ? И как это исправить?
java
functional-programming
java-8
java-stream
Дени Сегюре
источник
источник
IntStream
иStream<Integer>
?IntStream
- это потоковая специализация для примитивныхint
значений. AStream<Integer>
- это простоInteger
объекты Stream .IntStream
- это поток или примитивы (ints), тогдаSteram<Integer>
как это поток объектов. У примитивных потоков есть специальные методы по соображениям производительности.IntStream.mapToObj
ожидаетIntFunction
, функция, которая потребляетint
значение, поэтому.mapToObj((Integer i) -> i.toString())
не работает. В любом случае это не рекомендуется, поскольку содержит ненужное преобразование изint
вInteger
. Напротив, он.mapToObj(Integer::toString)
прекрасно работает, поскольку вызываетstatic
методInteger.toString(int)
. Обратите внимание, что это отличается от вызова.map(Integer::toString)
a,Stream<Integer>
поскольку последний не компилируется из-за неоднозначности..map(Integer::toString)
наStream<Integer>
действительно неоднозначна , поскольку оба,.map(i->i.toString())
и.map(i->Integer.toString(i))
являются действительными. Но это легко решить с помощью.map(Object::toString)
.Arrays.stream(numbers)
создает скрытый объект,IntStream
а операция картыIntStream
требуетIntUnaryOperator
(т.е. функцииint -> int
). Функция сопоставления, которую вы хотите применить, не соблюдает этот контракт и, следовательно, ошибку компиляции.Вам нужно будет позвонить
boxed()
раньше, чтобы получитьStream<Integer>
(это то, чтоArrays.asList(...).stream()
возвращается). Затем просто позвоните,map
как в первом фрагменте.Обратите внимание: если вам нужно
boxed()
, тоmap
вы, вероятно, захотите использоватьmapToObj
напрямую.Преимущество в том, что
mapToObj
не требуется помещать каждоеint
значение вInteger
объект; конечно, в зависимости от применяемой вами функции сопоставления; поэтому я бы выбрал этот вариант, который тоже короче.источник
Вы можете создать целочисленный поток, используя Arrays.stream (int []), вы можете вызвать
mapToObj
likemapToObj(Integer::toString)
.String csn = Arrays.stream(numbers) // your numbers array .mapToObj(Integer::toString) .collect(Collectors.joining(", "));
Надеюсь это поможет..
источник
Никакого бокса, AFAIK, и никакого взрыва маленьких строк в кучу:
public static void main(String[] args) { IntStream stream = IntStream.of(1, 2, 3, 4, 5, 6); String s = stream.collect(StringBuilder::new, (builder, n) -> builder.append(',').append(n), (x, y) -> x.append(',').append(y)).substring(1); System.out.println(s); }
источник
Если цель этого примера и вопроса - выяснить, как сопоставить строки с потоком целых чисел (например, используя поток целых чисел для доступа к индексу в массиве строк), вы также можете использовать бокс, а затем приведение к int (который затем позволит получить доступ к индексу массива).
int[] numbers = {0, 1, 2, 3}; String commaSeparatedNumbers = Arrays.stream(numbers) .boxed() .map((Integer i) -> Integer.toString((int)i)) .collect(Collectors.joining(", "));
Вызов .boxed () преобразует ваш IntStream (поток примитивных целых чисел) в Stream (поток объектов, а именно, объекты Integer), который затем принимает возврат объекта (в данном случае объекта String) из ваша лямбда. Здесь это просто строковое представление числа для демонстрационных целей, но с такой же легкостью (и более практично) им может быть любой строковый объект - например, элемент массива строк, как упоминалось ранее.
Просто подумал, что предлагаю другую возможность. В программировании всегда есть несколько способов выполнить задачу. Узнайте как можно больше, а затем выберите тот, который лучше всего подходит для поставленной задачи, учитывая проблемы производительности, интуитивность, ясность кода, ваши предпочтения в стиле кодирования и наиболее самодокументированный.
Удачного кодирования!
источник
int
в свой тип оболочкиInteger
и сразу после этого распаковываете.