89

From a char array, I want to construct a stream to use java 8 features such as filters and maps.

char[] list = {'a','c','e'};
Stream<Character> cStream = Stream.of(list);
// Stream<Character> cStream = Arrays.stream(list);

The first method does not work (Reason: change cStream to Stream<char[]>). The commented line does not also work (Reason: The method stream(T[]) in the type Arrays is not applicable for the arguments (char[])).

I know that if char[] list is changed to int[], everything works fine using IntStream. But I do not want to convert every char[] to int[] each time or change into a list when I need to use stream library on char array.

3
  • 2
    possible duplicate of Why is String.chars() a stream of ints in Java 8? Commented Jul 22, 2015 at 4:58
  • @heenenee That's certainly related, but I wouldn't call it a duplicate. Commented Jul 22, 2015 at 5:10
  • Although the other question is focused on why, the how is explained in its accepted answer. A single google search would've turned this up, and I guess I'm going by meta.stackoverflow.com/a/261593/2646526 Commented Jul 22, 2015 at 5:23

10 Answers 10

58

You can use an IntStream to generate the indices followed by mapToObj:

char[] arr = {'a','c','e'};
Stream<Character> cStream = IntStream.range(0, arr.length).mapToObj(i -> arr[i]);
Sign up to request clarification or add additional context in comments.

Comments

55

A way to do this is via a String object:

char[] list = {'a','c','e'};
Stream<Character> charStream = new String(list).chars().mapToObj(i->(char)i);

I like to do it this way because all the complexity of transforming the array is wrapped into the String creation, and the wrapping of char is also performed behind the scene for me so I can focus on the business logic.

2 Comments

Semantically not different to this answer, except that using CharBuffer.wrap(list) is more efficient than new String(list) as it does not involve copying the array resp., starting with Java 9, converting the char array to a byte array and converting it back while streaming. Under Java 8, the difference is even bigger as String.chars() has been poorly implemented whereas CharBuffer.chars() has an efficient implementation. That has been solved with Java 9, but the copying/conversion overhead of new String(char[]) remains.
Note that sometimes, when you have an array of characters, it's because it's a sensitive value (like a password), and you're explicitly avoiding instantiating a String. stackoverflow.com/questions/8881291/…
39

A short and efficient way to create an IntStream from char[] array is to use java.nio.CharBuffer:

char[] list = {'a','c','e'};
IntStream stream = CharBuffer.wrap(list).chars();

This way you can use an IntStream interpreting the int values as characters. If you want a boxed Stream<Character> (which may be less efficient), use

Stream<Character> stream = CharBuffer.wrap(list).chars().mapToObj(ch -> (char)ch);

Using CharBuffer can be a little bit faster than IntStream.range as it has custom spliterator inside, so it does not have to execute an additional lambda (possibly as slow polymorphic call). Also it refers to the char[] array only once and not inside the lambda, so it can be used with non-final array variable or function return value (like CharBuffer.wrap(getCharArrayFromSomewhere()).chars()).

1 Comment

I really like that solution since it doesn't copy the elements of array while still avoiding autoboxing.
3

The simplest change you can make to the code is change char[] to Character[].

Another way is to create a new ArrayList of the boxed chars:

char[] list = {'a','c','e'};
List<Character> listArray = new ArrayList<>();
for (char c : list)
    listArray.add(c);
Stream<Character> cStream = listArray.stream();

In addition, you can use Google Guava's Chars class, to replace the for loop with:

List<Character> listArray = Chars.asList(list);

Comments

2
"ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars().mapToObj(i -> (char) i);

Comments

2

How about a workaround: char[] list = {'a','c','e'};

Arrays.asList(list).stream();

1 Comment

Downvote. You didn't even try this. It doesn't do what you think it does.
2

Another way not mentioned: make a new String

char[] arr = {'a','c','e'};
new String(arr).chars().mapToObj(i -> (Character) (char) i);

Comments

1

Getting substream of Characters

 String givenString = "MyNameIsArpan";

       Object[] ints = givenString.chars().mapToObj(i -> (char)i).toArray();

       String subString = Arrays.stream(ints,2,6).
                             map(i -> (char)i).
                             map(String::valueOf).
                             collect(Collectors.joining());

      System.out.println(subString);

OUTPUT : Name

Comments

0

Using Stream Builder:

String inputString = "This is string";
Stream.Builder<Character> charStreamBuilder = Stream.builder();
for (char i :inputString.toCharArray()) {
   charStreamBuilder.accept(i);
 }
 Stream<Character> characterStream = charStreamBuilder.build();

Comments

-6

I believe the simplest way to convert to Character stream is

    char[] list = {'a','c','e'};

    Stream<Character> characters = Stream.ofAll(list);

2 Comments

Although interesting, this answer is not valid because the question is about JDK Steams, and it seems you are referring to javaslang streams.
If someone needs to know, he is referring to the www.vavr.io

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.