2

I am about to create the two dimensional array from string:

char[][] chars;
String alphabet = "abcdefghijklmnopqrstuvwxyz";

So the array will ilustrate this matrix: enter image description here

But how can I do that using Java 8 Streams, cause I do not want to do this by casual loops ?

5
  • 1
    Why not just use loops? It will be so much clearer. Commented Dec 11, 2017 at 23:56
  • @AndyTurner I know that streams do not provide good readbility, but just want to do that using streams as a curosity. Commented Dec 11, 2017 at 23:58
  • 1
    Streams provide great readability... when used appropriately. Commented Dec 12, 2017 at 0:15
  • 1
    You can't do this elegantly with streams because there's unfortunately no CharStream. Commented Dec 12, 2017 at 0:17
  • Thank you guys, don't blame me for that. I just was interested how to that using Streams :) Commented Dec 12, 2017 at 0:18

2 Answers 2

9

Poor loops. They get such a bad rap. I doubt a streams-based solution would be as clear as this:

int n = alphabet.length();
char[][] cs = new char[n][n];
for (int i = 0; i < n; ++i) {
  for (int j = 0; j < n; ++j) {
    cs[i][j] = alphabet.charAt((i + j) % n);
  }
}

If I had to do it with streams, I guess I'd do something like this:

IntStream.range(0, n)
    .forEach(
        i -> IntStream.range(0, n).forEach(j -> cs[i][j] = alphabet.charAt((i + j) % n)));

Or, if I didn't care about creating lots of intermediate strings:

cs = IntStream.range(0, n)
    .mapToObj(i -> alphabet.substring(i) + alphabet.substring(0, i))
    .map(String.toCharArray())
    .toArray(new char[n][]);

A slightly more fun way to do it:

char[][] cs = new char[n][];
cs[0] = alphabet.toCharArray();
for (int i = 1; i < n; ++i) {
  cs[i] = Arrays.copyOfRange(cs[i-1], 1, n+1);
  cs[i][n-1] = cs[i-1][0];
}
Sign up to request clarification or add additional context in comments.

Comments

2

You can use Stream.iterate() to rotate each string incrementally and then convert them to char arrays:

chars = Stream.iterate(alphabet, str -> str.substring(1) + str.charAt(0))
        .limit(alphabet.length())
        .map(String::toCharArray)
        .toArray(char[][]::new);

Or you can rotate each string by its index, with Apache's StringUtils.rotate():

chars = IntStream.range(0, alphabet.length())
        .mapToObj(i -> StringUtils.rotate(alphabet, -i))
        .map(String::toCharArray)
        .toArray(char[][]::new);

Or with Guava's Chars utility class:

chars = Stream.generate(alphabet::toCharArray)
        .limit(alphabet.length())
        .toArray(char[][]::new);

IntStream.range(0, chars.length)
        .forEach(i -> Collections.rotate(Chars.asList(chars[i]), -i));

Comments

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.