Как заполнить map?

260
02 ноября 2017, 05:05

Задача следующая: мне надо написать метод, который на вход принимает какой либо текст и возвращает Map, которая хранит количество повторений каждого буквенного символа в этом тексте. Я разбил строку на массив символов, сохранил в ArrayList, отсортировал его, затем посчитал сколько раз повторяется каждый символ и теперь надо это занести в Map. Вот то, что я пока сделал:

public static Map<Character, Integer> countSymbolsNew(String text)throws Exception{
        //сделать отсортированный список
        //посчитать количество повторений каждого символа и занести в переменную
        //результат добавить в мапу
        if (text == null)
            throw new Exception("No text");
    Map<Character, Integer> map = new HashMap<>();
    ArrayList<Character> chars = new ArrayList<>();
    for (int i = 0; i < text.length(); i++) {
        char c = text.toLowerCase().charAt(i);
        if (Character.isLetter(c)){
            chars.add(c);
        }
    }
    Collections.sort(chars);
    System.out.println(chars);
    //надо взять первый элемент массива, пройти им по всему списку и если повторяется то плюсовать счетчик
    //если не повторился то счетчик равен 1
    int maxCount = 0;
    for (Character aChar : chars) {
        int count = 0;
        for (Character ch : chars) {
            if (aChar.equals(ch)){
                count++;
            }
        }
        if (count > maxCount){
            maxCount = count;
        }
        System.out.print(count + " ,");
    }

    return map;
}

Теоретически я вроде представляю как добавляются элементы в Map, а на практике вот что-то не могу дальше ничего сделать. Прошу помощи и объяснений.

Answer 1

Если "ментор" предложил сортировать массив и явно боится сделать лишний раз put (ну мало какой там бзык в голове у человека), то можно сделать и так. В принципе просто добавление map.put(aChar, count) уже решает задачу, и даже @Roman Danilov это и написал. Но у этого решение есть один минус - квадратичная сложность. И если бы массив не был отсортирован, то можно было бы наверно и закрыть глаза на это. Но массив уже отсортирован, поэтому, одинаковые элементы идут подряд. Нужно только бежать и суммировать. Где то так

public static Map<Character, Integer> countSymbolsNew(String text)throws Exception{
        //сделать отсортированный список
        //посчитать количество повторений каждого символа и занести в переменную
        //результат добавить в мапу
        if (text == null)
            throw new Exception("No text");
    Map<Character, Integer> map = new HashMap<>();
    ArrayList<Character> chars = new ArrayList<>();
    for (int i = 0; i < text.length(); i++) {
        char c = text.toLowerCase().charAt(i);
        if (Character.isLetter(c)){
            chars.add(c);
        }
    }
    Collections.sort(chars);
    System.out.println(chars);
    Character c = chars.get(0);
    int count = 1;
    for (int i = 1; i < chars.size(); i++) {
        // проверим текущий символ. я не знаю, можно ли тут просто равно
        if (chars.get(i).equals(c)) {
            // символ тот же - просто счетчик увеличим
            count++;
        } else {
           // другой символ, добавим предыдущий и запомним новый
            map.put(c, count);
            c = chars.get(i);
            count = 1;
        }
    }
    // а это уже хвост, который также нужно обработать.
    map.put(c, count);
    return map;
}
Answer 2

Если по простому и без возможностей Java8, то достаточно этого:

public static Map<Character, Integer> countSymbolsNew(String text)throws Exception {
    if (text == null)
        throw new Exception("No text");
    Map<Character, Integer> map = new HashMap<>();
    for (int i = 0; i < text.length(); i++) {
        char c = text.toLowerCase().charAt(i);
        if (Character.isLetter(c)) {
            if (map.containsKey(c)) {
                map.put(c, map.get(c) + 1);
            } else {
                map.put(c, 1);
            }
        }
    }
    return map;
}

Здесь мы просто перебираем массив символов и кладем каждый символ в мапу. А если такой символ уже есть, просто кладем в мапу тот же символ, но с увеличенным счетчиком, старый при этом затирается.

Если принципиально делать так, как делаете вы, то можно сделать следующим образом:

//надо взять первый элемент массива, пройти им по всему списку и если повторяется то плюсовать счетчик
//если не повторился то счетчик равен 1
for (Character aChar : chars) {
    if (!map.containsKey(aChar)) {
        int count = 0;
        for (Character ch : chars) {
            if (aChar.equals(ch)){
                count++;
            }
        }
        System.out.print(count + " ,");
        map.put(aChar, count);
    }
}
Answer 3
public Map <Character, Integer> letterCalculate (String text){
    Map <Character, Integer> mapCounter = new TreeMap <>();
    for (char ch : text.toCharArray()) {
        if (Character.isLetter(ch)) mapCounter.put(ch, mapCounter.get(ch) == null ? 1 : mapCounter.get(ch) + 1);
    }
    return mapCounter;
}
READ ALSO
Error:(52, 33) error: incompatible types: ClearDB cannot be converted to Context

Error:(52, 33) error: incompatible types: ClearDB cannot be converted to Context

Помогите решить проблемуВ классе ClearDB хочу реализовать разные методы работы с базой (добавить запись, удалить, очистить базу

274
Динамическая подстановка запроса в JasperReports

Динамическая подстановка запроса в JasperReports

Новичок в JR, пытаюсь разобратьсяЕсть приложение, которое выводит данные из БД в зависимости от выбранных условий (отмеченных флагов), причем...

248
Проблема подключения с Windows на Linux

Проблема подключения с Windows на Linux

Есть код на JAVA, не могу подключиться с винды на linux (из 50 попыток одна удалась), хотя в обратную сторону всё корректно работает, в чем может быть...

229