Stream.flatMap () из char [] в поток символов - PullRequest
3 голосов
/ 05 мая 2020
import java.util.*; 
import java.util.stream.*; 

class Playground { 

    public static void main(String[] args) 
    { 
        // Creating a character array 
        char arr[] = { '1', '2', '3', '4', '5' }; 

        // --------- Using Stream.of() --------- 
        // Will work efficiently 

        // to convert int array into Stream 
        Stream<char[]> stream = Stream.of(arr); 
        Stream<Integer> s = stream.flatMap((item)->new String(item).chars().mapToObj(a->(char)a));

        // Displaying elements in Stream 
        s.forEach(str -> System.out.print(str + " ")); 
    } 
} 

Я пытаюсь преобразовать char [] в поток символов с помощью flatMap (), но получаю следующую ошибку:

./Playground/Playground.java:14: error: incompatible types: inference variable R has incompatible bounds
        Stream<Integer> s = stream.flatMap((item)->new String(item).chars().mapToObj(a->(char)a));
                                          ^
    equality constraints: Integer
    lower bounds: U,Character
  where R,T,U are type-variables:
    R extends Object declared in method <R>flatMap(Function<? super T,? extends Stream<? extends R>>)
    T extends Object declared in interface Stream
    U extends Object declared in method <U>mapToObj(IntFunction<? extends U>)
1 error

Нужна помощь в понимании ошибки и способах ее выполнения sh это задание. В частности, как это исправить эту строку кода, используя flatMap () из char [] в поток символов. испортил набор текста после случайного исправления лямбда-выражения. Исходная строка была

Stream<Character> s = stream.flatMap(item->{new String(item).chars().mapToObj(a->(char)a);});

, и проблема заключалась в отсутствии оператора возврата внутри {}. Затем я изменил строку на

Stream<Integer> s = stream.flatMap((item)->new String(item).chars())

, потому что думал, что IntStream :: mapToObj вызывает проблемы, однако я забыл о boxed () в конце и получил другую ошибку типа, поэтому я добавил IntStream :: mapToObj и опубликовал вопрос, но забыл изменить тип потока обратно на Character. Я запуталась, но туман рассеялся. Спасибо за хорошие ответы.

Ответы [ 4 ]

3 голосов
/ 05 мая 2020

Непонятно, чего вы пытаетесь достичь этим обходным путем из ненужных операций. Если вы хотите выполнить потоковую передачу по массиву, просто начните с этой операции, вместо создания потока одного элемента, чтобы связать flatMap, чтобы связать другой map.

Ваш код уже содержит подход для потоковая передача по массиву char[] в середине других операций с использованием конструктора String.

char[] arr = { '1', '2', '3', '4', '5' };

new String(arr).chars().forEach(i -> System.out.print(i + " "));

Это напечатает числа Unicode. Если вы хотите вместо этого печатать символы, просто измените операцию терминала:

new String(arr).chars().forEach(i -> System.out.print((char)i + " "));

или

new String(arr).chars().forEach(i -> System.out.printf("%c ", i));

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

new String(arr).chars().mapToObj(i -> (char)i).forEach(i -> System.out.print(i+" "));

, но это касается бокса накладные расходы, поскольку он создает Stream<Character>.


Обратите внимание, что new String(arr) несет накладные расходы на копирование, поскольку создает неизменяемый объект. Вы можете избежать этого, используя

CharBuffer.wrap(arr).chars().forEach(i -> System.out.printf("%c ", i));

. Конечно, вы можете вставить столько завитушек, сколько захотите, например,

Stream.of(arr)
    .flatMapToInt(array -> CharBuffer.wrap(array).chars())
    .mapToObj(i -> (char)i) // returns a Stream<Character> not Stream<Integer>
    .forEach(i -> System.out.printf("%c ", i));

, но для этого нет причин.

2 голосов
/ 05 мая 2020

Вы использовали Stream<Integer> вместо Stream<Character>. Если вы хотите использовать Stream<Integer>, вам нужно использовать IntStream :: boxed или mapToObj(a -> Integer.valueOf(a)), как показано ниже:

import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        char arr[] = { '1', '2', '3', '4', '5' };

        Stream<char[]> stream1 = Stream.of(arr);
        Stream<Character> chars = stream1.flatMap(item -> new String(item).chars().mapToObj(a -> (char) a));
        chars.forEach(c -> System.out.print(c + " "));

        System.out.println();

        Stream<char[]> stream2 = Stream.of(arr);
        Stream<Integer> ints = stream2.flatMap(item -> new String(item).chars().boxed());
        ints.forEach(i -> System.out.print(i + " "));

        System.out.println();

        Stream<char[]> stream3 = Stream.of(arr);
        Stream<Integer> integers = stream3.flatMap(item -> new String(item).chars().mapToObj(a -> Integer.valueOf(a)));
        integers.forEach(i -> System.out.print(i + " "));
    }
}

Вывод:

1 2 3 4 5 
49 50 51 52 53 
49 50 51 52 53 
2 голосов
/ 05 мая 2020

Вы были почти у цели. Просто замените Stream<Integer> на Stream<Character>, поскольку вы выполняете приведение к char в своем коде.

Однако проблема вашего кода в том, что вы без необходимости flatMap ping . Stream.of ожидает массив со ссылочным типом в качестве его составного типа. Далее, Arrays.stream не имеет перегрузки для char[]. В конечном итоге вы транслируете что-то, что гарантированно будет одним элементом. Этот элемент - ваш char[].

Вы можете просто отбросить операцию flatMap и напрямую преобразовать массив символов в String.

String str = new String(arr);
Stream<Character> characterStream = str.chars().mapToObj(c -> (char) c);
2 голосов
/ 05 мая 2020
  • Вы можете использовать Arrays.stream() для любого массива, кроме byte, char или short.
  • Вы можете использовать *Stream.of() для любого примитивного массива типа *, где * - Int или Double, или Long .
  • Вы можете использовать Stream.of() для любого массива объектов.

Все следующие действия выполняются, как описано выше.

Integer[] IntegerArray = {1,2,3,4};
Arrays.stream(IntegerArray).forEach(System.out::println);
Stream.of(IntegerArray).forEach(System.out::println);

int[] intArray = {1,2,3,4};
Arrays.stream(intArray).forEach(System.out::println);
IntStream.of(intArray).forEach(System.out::println);

double[] doubleArray = {1.2,3.3,4.5,6.7};
Arrays.stream(doubleArray).forEach(System.out::println);
DoubleStream.of(doubleArray).forEach(System.out::println);

String[] stringArray = {"a","b","c","d"};
Stream.of(stringArray).forEach(System.out::println);

Для решения вашей реальной проблемы, попробуйте это.

     // Creating a character array 
        char arr[] = { '1', '2', '3', '4', '5' }; 

        // --------- Using Stream.of() --------- 
        // Will work efficiently 

        // to convert int array into Stream 
        Stream<char[]> stream = Stream.of(arr); 


        // Displaying elements in Stream 
        s.forEach(str -> System.out.print(str + " ")); 
        Stream<Integer> s = stream.flatMapToInt((item)->(new String(item)).chars()).boxed();
        //or
        IntStream s = stream.flatMapToInt((item)->(new String(item)).chars());

        // Displaying elements in Stream 
        s.forEach(str -> System.out.print((char)str + " ")); 



...