user3597269
user3597269

Reputation: 49

Enclosing scope must be final with Java Streams

When trying to count the number of chars in a string using streams I get an error "Local variable i defined in an enclosing scope must be final or effectively final" What do you use as a work around in this case? Would I just have to do it separately without looping it? I'm a student and the task is decrypting Caesar cipher so freq analysis is part of this.

Thank you.

public static int[] freqAnalyse(String text) {
    int[] frequencies = new int[26];
    String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    text = text.toUpperCase();
    for(int i = 0; i < 26; i++) {
        frequencies[i] = (int) text.chars().filter(k -> k == alphabet.charAt(i)).count();
    }
    return frequencies;
}

EDIT This works, is this bad practice or just what it wants? Thank you.

public static int[] freqAnalyse(String text) {
        int[] frequencies = new int[26];
        String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        text = text.toUpperCase();
        for(int i = 0; i < 26; i++) {
            final int j = i;
            frequencies[j] = (int) text.chars().filter(k -> k == alphabet.charAt(j)).count();
        }
        return frequencies;
    }

Upvotes: 0

Views: 147

Answers (3)

Manik Jain
Manik Jain

Reputation: 86

May be you can try doing something like this :

public static int[] freqAnalyse(String text) {
    int[] frequencies = new int[26];
    String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    text = text.toUpperCase();
    for(int i = 0; i < 26; i++) {
        final char c = alphabet.charAt(i);
        frequencies[i] = (int) text.chars().filter(k -> k == c).count();
    }
    return frequencies;
}

Upvotes: 1

MD Ruhul Amin
MD Ruhul Amin

Reputation: 4502

In those cases, You can also completely ignore the count variable i using iterator. Here is an other way to do it:

        int[] frequencies = new int[26];
        String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        text = text.toUpperCase();
        for (char c : alphabet.toCharArray()) {
            frequencies[c-'A'] = (int)text.chars().filter(value -> value == c).count();
        }

Using only stream one liner:

    String upperCase = text.toUpperCase();
    alphabet.chars().forEach(ch -> frequencies[ch-'A'] = (int)upperCase.chars().filter(value -> value == ch).count());  

Upvotes: 1

Louis Wasserman
Louis Wasserman

Reputation: 198093

The simplest workaround is to copy i into a new variable.

 final int ii = i;
 frequencies[i] = (int) text.chars().filter(k -> k == alphabet.charAt(ii)).count();

Alternately, you could just store a variable for that character:

final char ch = alphabet.charAt(i);
frequencies[i] = (int) text.chars().filter(k -> k == ch).count();

Upvotes: 2

Related Questions