Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Two dimensional char array from string using Stream

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 ?

like image 676
masterofdisaster Avatar asked Dec 11 '25 13:12

masterofdisaster


2 Answers

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];
}
like image 117
Andy Turner Avatar answered Dec 14 '25 04:12

Andy Turner


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));
like image 26
shmosel Avatar answered Dec 14 '25 02:12

shmosel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!