9

I am writing a program in which a method takes char[][] as input and returns char[]. Method is as below -

private static char[] getTableFromTwoChits(char[][] inputTwoChits) {
    Map<Character, Character> map = new HashMap<>();
    Arrays.stream(inputTwoChits).forEach(x -> map.put(x[0], x[1]));
    map.entrySet().forEach(System.out::println);
    char[] result = new char[inputTwoChits.length+1]; int index=0;
    char startPoint = inputTwoChits[0][0];
    do {
       result[index] = startPoint;index++;
       startPoint = map.get(startPoint);
    }while(startPoint != inputTwoChits[0][0]);
    result[index] = startPoint;
    return result;
}


Main method is as follows -

public static void main(String[] args) {
    char[][] inputTwoChits = {{'A','B'},{'C','D'},{'B','C'},{'E','F'},{'F','A'},{'D','E'}};
    char[] outputTwoChits = getTableFromTwoChits(inputTwoChits);
    Arrays.stream(outputTwoChits).forEach(System.out::println);

}


Line 2 in the method getTableFromTwoChits() is compiling fine, whereas line 3 of main method is not compiling.
Please explain what is the reason behind such behaviour?

Compilation error is mentioned as below -

/CircularTableTwoChits.java:21: error: no suitable method found for stream(char[])
        Arrays.stream(outputTwoChits).forEach(System.out::println);
              ^
    method Arrays.<T#1>stream(T#1[]) is not applicable
      (inference variable T#1 has incompatible bounds
        equality constraints: char
        upper bounds: Object)
    method Arrays.<T#2>stream(T#2[],int,int) is not applicable
      (cannot infer type-variable(s) T#2
        (actual and formal argument lists differ in length))
    method Arrays.stream(int[]) is not applicable
      (argument mismatch; char[] cannot be converted to int[])
    method Arrays.stream(long[]) is not applicable
      (argument mismatch; char[] cannot be converted to long[])
    method Arrays.stream(double[]) is not applicable
      (argument mismatch; char[] cannot be converted to double[])
  where T#1,T#2 are type-variables:
    T#1 extends Object declared in method <T#1>stream(T#1[])
    T#2 extends Object declared in method <T#2>stream(T#2[],int,int)
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error
Eran
  • 387,369
  • 54
  • 702
  • 768
ash164
  • 231
  • 3
  • 9

5 Answers5

11

There are only four stream types, for elements of type int, long, double, and reference types (objects). So, since there is no char stream, Arrays.stream can’t be applied to a char[] array.

The canonical representation of a stream of characters is an IntStream and acquiring it without copying or boxing overhead works like

CharBuffer.wrap(charArray).chars().forEach(c -> System.out.println((char)c));

Since the default interpretation of int values is “integer number”, you need to use the lambda expression casting it to char to interpret it as “character”.

If you don’t need linebreaks between the characters, you can simply print the entire array in one line via

System.out.println(String.valueOf(charArray));
Holger
  • 285,553
  • 42
  • 434
  • 765
8

You cannot create a CharStream with Arrays.stream(outputTwoChits) as there is no overload in the Arrays class that takes a char[] and returns a CharStream (infact there is no CharStream at all) and doing Stream.of(outputTwoChits) would not provide what you'd expect in this particular case.

However, since you're only doing this for printing purposes you can do something like:

Arrays.stream(new String(outputTwoChits).split("")).forEach(System.out::println);

or construct a String object from the char array and call the chars method on it which should produce an IntStream and then project from int to char prior to printing to the console.

new String(outputTwoChits).chars().forEach(c -> System.out.println((char)c));
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
5

In

Arrays.stream(inputTwoChits)

you are passing a char[][] array to <T> Stream<T> stream(T[] array), which is fine, since char[] is a reference type.

On the other hand, in

Arrays.stream(outputTwoChits)

you are passing a char[], and char is not a reference type, so it doesn't match the signature of <T> Stream<T> stream(T[] array).

You can produce an IntStream from a char[] using:

new String(outputTwoChits).chars()
Eran
  • 387,369
  • 54
  • 702
  • 768
  • This is also a possible solution. But changing the method to return Character[] instead of char[] also worked. – ash164 Jan 03 '18 at 17:47
3

Character wrapper class

You are trying to make a stream of char which is of type primitive. Try this code with the wrapper class Character. You will get the desired output.

Roman C
  • 49,761
  • 33
  • 66
  • 176
Shailesh Tanwar
  • 122
  • 1
  • 9
  • 7
    Your logic is flawed. int is primitive as well but you can still call Arrays.stream on it. – whatamidoingwithmylife Jan 01 '18 at 16:28
  • 2
    Thank you for pointing that out. You are right we can create stream using array of int, long and double by arrays.stream which returns IntStream, LongStream and DoubleStream respectively but there is no method in arrays class for char which return a stream of char. – Shailesh Tanwar Jan 02 '18 at 06:53
  • Character[] will work as Object[] method exists in stream – ash164 Jan 03 '18 at 17:39
2

You can use the static method IntStream.range() which can be used as follows to create a Stream of indices and then use them to map the values in the charArray to a Character-stream:

Stream<Character> chars = IntStream.range(0, charArray.length)
    .mapToObj(i -> charArray[i]);

The .mapToObj() method is used, because we're operating on an IntStream and we want to convert the unboxed primitive stream to a boxed reference stream.

Lino
  • 19,604
  • 6
  • 47
  • 65