local variables referenced from a lambda expression must be final or effectively final при фильтрации символов в строке

190
07 октября 2018, 09:10

Решаю задачку. В общем, начальную строку нужно преобразовать в новую, заменив все повторяющиеся символы на правую скобочку ')', а все уникальные - на левую '('.

Мое решение:

public class DuplicateEncoder {
  static String encode(String word) {
    String newWord = "";
    char[] chArray = word.toCharArray();
    for (int i = 0; i < word.length(); i++) {
      if (word.chars().filter(num -> num == chArray[i]).count() > 1)
        { newWord = newWord + "("; }
      else 
        { newWord = newWord + ")"; }
    }
    return newWord;
  }
}

В нем такая ошибка:

/workspace/java/src/DuplicateEncoder.java:6: error: local variables referenced from a lambda expression must be final or effectively final
      if (word.chars().filter(num -> num == chArray[i]).count() > 1)
                                                    ^
1 error

Как исправить эту ошибку?

Answer 1

Захваченное лямбда-выражением локальное значение должно быть effectively final. Этого можно добиться, например, с помощью создания final-переменной:

final ch = chArray[i];
if (word.chars().filter(num -> num == ch).count() > 1)

А вообще можно переписать решение, чтобы оно работало не за O(n^2), а за O(n) (n - длина слово).
Для этого достаточно проходить по слову два раза: первый раз для подсчета количества вхождений символов и сохранения результатов в Map, а второй - для сбора итоговой строки по данным из Map.
Также для сбора строки лучше использовать StringBuilder, а не конкатенацию строк.

Итоговый код:

static String encode(String word)
{
    HashMap<Character, Integer> charToCount = new HashMap<>();
    char[] chars = word.toLowerCase().toCharArray();
    for (char ch : chars)
    {
        int currentCount = charToCount.containsKey(ch) ? charToCount.get(ch) : 0;
        charToCount.put(ch, currentCount + 1);
    }
    StringBuilder sb = new StringBuilder(word.length());
    for (char ch : chars)
    {
        char replaceChar = charToCount.get(ch) == 1 ? '(' : ')';
        sb.append(replaceChar);
    }
    return sb.toString();
}

P.S. Зашел на сайт задания - нужно ещё игнорировать регистр букв, добавил это в код

READ ALSO
Закругленный фон в счётчике Navigtion Drawer

Закругленный фон в счётчике Navigtion Drawer

Нужно сделать закругленные края в счётчике Navigation Drawer, на картинке, без использования библиотеки

141
В чем причина получения default значения при Intent?

В чем причина получения default значения при Intent?

Пытаюсь передать int значение из одного класса в другой, но значение не передается и присваивается default значение

158
Как вытащить данные из сессии для других активностей [закрыт]

Как вытащить данные из сессии для других активностей [закрыт]

Приведу пример своей реализацииЧать класс Utils:

165
Выбор способа вывода текста для консоли приложения

Выбор способа вывода текста для консоли приложения

Есть консоль, которая реализована с помощью TextFlow, там цветные сообщения (если ошибка - красное, предупреждение - желтое и тд)TextFlow не дает выделять...

169