【问题标题】:Stream.flatMap() from char[] to Character streamStream.flatMap() 从 char[] 到字符流
【发布时间】:2020-05-04 22:26:40
【问题描述】:
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 + " ")); 
    } 
} 

我正在尝试使用 flatMap() 将 char[] 转换为字符流,但出现以下错误

./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

需要帮助以了解错误以及如何完成此任务。具体如何使用 flatMap() 从 char[] 到字符流来修复这行代码。

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

编辑:所以问题不是关于 Stream 而是关于 lambda 表达式,我在意外修复 lambda 表达式后抽搐了线路并弄乱了打字。原行是

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

问题是 {} 中缺少 return 语句。然后我把这条线改成了

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

因为我认为 IntStream::mapToObj 造成了麻烦但是我最后忘记了 boxed() 并得到了另一个类型错误,所以我添加了 IntStream::mapToObj 并发布了问题但忘记将 Stream 类型更改回特点。我很困惑,但现在雾已经散去。谢谢你的好答案。

【问题讨论】:

  • 只要Arrays.stream(array)
  • @WJS 不适用于char[]
  • @Holger Nuts!也不是short[] 也不是byte[]。我一直忘记这些类型没有重载。我必须在下面修改我的答案才能修复。非常感谢!
  • 谢谢大家。所以问题原来不是关于 Stream 而是关于 lambda 表达式,我在意外修复 lambda 表达式后抽搐了线路并弄乱了打字。原行是“Stream s = stream.flatMap(item->{new String(item).chars().mapToObj(a->(char)a);});”问题是 {} 中缺少 return 语句。我在更改线路后创建了新错误,并且错误消息有点模糊,对我来说很糟糕。再次感谢您的好答案:)

标签: java java-stream lambda


【解决方案1】:

你快到了。只需将 Stream&lt;Integer&gt; 替换为 Stream&lt;Character&gt;,因为您将在代码中转换为 char

但是,关于您的代码的问题在于您不必要地flatMappingStream.of 需要一个具有引用类型的数组作为其复合类型。此外,Arrays.stream 没有char[] 的重载。你最终会流过一些保证是单个元素的东西。该元素是您的char[]

你可以去掉flatMap操作,直接把char数组转成String。

String str = new String(arr);
Stream<Character> characterStream = str.chars().mapToObj(c -> (char) c);

【讨论】:

  • 谢谢!我很困惑,犯了一些愚蠢的错误。
【解决方案2】:

通过这种不必要的操作绕道而行,你还不清楚你想达到什么目的。当您想通过数组流式传输时,只需从该操作开始,而不是创建单个元素流,链接 flatMap,链接另一个 map

您的代码确实已经包含在其他操作中间使用String 构造函数在char[] 数组上进行流式传输的方法。

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&lt;Character&gt;


请注意,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));

但没有理由这样做。

【讨论】:

  • 感谢您的全面解答!刚开始使用 lambda 表达式和 Stream,到处测试水,看看它们做了什么。
【解决方案3】:

您使用了Stream&lt;Integer&gt; 而不是Stream&lt;Character&gt;。如果要使用Stream&lt;Integer&gt;,则需要使用IntStream::boxedmapToObj(a -&gt; 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 

【讨论】:

  • 谢谢!很有帮助的答案。我从“Stream s = stream.flatMap(item->{new String(item).chars().mapToObj(a->(char)a);});”开始然后切换到 Stream,原来 {} 是问题所在。似乎我不能对 1 行 lambda 表达式使用大括号。 “Stream s = stream.flatMap(item->new String(item).chars().mapToObj(a->(char)a));”所以去掉大括号后这条线可以正常工作。不完全确定为什么,在理解 lambda 表达式的这一部分之前,我可能需要对泛型有更好的理解。
  • @Luke 当你想使用{} 时,你还必须使其内容成为一个(return)声明:item -&gt; { return expression; }
  • @ArvindKumarAvinash 哦,是的,我在使用 {} 时遗漏了 return 语句。谢谢!
【解决方案4】:
  • 您可以将 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 + " ")); 



【讨论】:

  • 感谢您的回答,但我试图了解这行代码出了什么问题 "Stream s = stream.flatMap((item)->new String(item) .chars().mapToObj(a->(char)a));"和可能的修复。顺便说一句,您只能将 Arrays.stream() 用于具有相应原始类型流(intstream、longstream、doublestream)的原始类型数组。
  • 试试这个IntStream s = stream.flatMapToInt((item)-&gt;(new String(item)).chars()).map(c-&gt;(char)c);
  • 请记住,chars 被视为 ints,当您打印它们时,您需要再次将它们转换为 char。所以最后一个映射到 char 的用处不大。
  • 非常有帮助,我现在明白了。谢谢!:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-27
  • 1970-01-01
  • 2016-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多