Как сделать двойную сортировку в HashSet или чем его заменить?
Есть задача:
Реализуйте
countWords()метод в классеWords. Входной параметр - это список строк, представляющих строки текста. Подсчет слов - сопоставление слов в нижнем регистре с их частотой в тексте. Если слово «котик» встречается в тексте 23 раза, то его записью будет «котик - 23 \ n» . Пропускать любое слово длиной менее 4 и частотой менее 10 (например, слишком маленькие или слишком редкие слова). Возвращает строку, содержащую все записи. Записи в результирующей строке также следует отсортировать по количеству, а затем, если необходимо, в алфавитном порядке. Вы не можете использовать потоки или лямбды в своем коде.
Вот что пока получилось:
public class Words {
List<String> words = new ArrayList<>();
List<String> newWords = new ArrayList<>();
ArrayList<String> againWords = new ArrayList<>();
Hashtable<String, Integer> heshWord = new Hashtable<>();
//String endString;
String up;
public String countWords(List<String> lines) {
words.addAll(lines);//Приняли все строки, сложили в words
Pattern pattern = Pattern.compile("[^a-zA-Zа-яёА-ЯЁ]+", Pattern.CASE_INSENSITIVE);//Паттерн что бы отсеять при переборе
ListIterator iterator = words.listIterator();//Итератор по words
while (iterator.hasNext()) {
String stringLine = (String) iterator.next();
String str = stringLine.replaceAll(pattern.pattern(), " ").toLowerCase(Locale.ROOT);//отсеять все по патерну
String[] strMassive = str.split(" ");
for (String s : strMassive) {
if (s.length() > 3) {//Убрать слова меньше 4 букв
newWords.add(s);
}
}
}
Set<String> setString = new HashSet<String>(newWords);
for (String s : setString) {
System.out.println(s + " - " + Collections.frequency(newWords, s));
int num = Collections.frequency(newWords, s);
//1. Отсортировать по кол-ву повторений, потом, если есть повторы, то по алфавиту
//2. Перенести в String и вернуть.
up= newWords.toString();
}
return up;
}
}
Проблемы:
- Не получается сделать сортировку в
HashSetпо количеству совпадений (а потом еще и по алфавиту, если несколько с одинаковым кол-вом совпадений), что лучше вместо него использовать и как? НапрашиваетсяHashMap, но и с ним пока не работает. - Как перенести получившийся лист в
String? Как не пытаюсь либо выходит ссылка на строку, либо строка которую нельзя редактировать.
Подскажите пожалуйста, в каком направлении смотреть?
Ответы (1 шт):
Если стримы под запретом, то придется делать что-то в этом духе:
import java.util.*;
public class WordsCounter {
private final int minWordLength, minCount;
public WordsCounter(int minWordLength, int minCount) {
this.minWordLength = minWordLength;
this.minCount = minCount;
}
public List<WordCount> countWords(String text, String regexDelimeter) {
return sortWithLimit(getWordsCount(text.split(regexDelimeter)));
}
private Map<String, WordCount> getWordsCount(String[] text) {
Map<String, WordCount> map = new HashMap<>();
for (String word : text) {
if (word.length() < minWordLength) continue;
String lowerCaseWord = word.toLowerCase();
map.put(lowerCaseWord, map.containsKey(lowerCaseWord)
? map.get(lowerCaseWord).addCount() : new WordCount(word));
}
return map;
}
private List<WordCount> sortWithLimit(Map<String, WordCount> map){
List<WordCount> list = new ArrayList<>(map.values());
Collections.sort(list);
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getCount() > minCount) {
return list.subList(i, list.size());
}
}
return new ArrayList<>(0);
}
}
class WordCount implements Comparable<WordCount> {
private final String value;
private Integer count;
public WordCount(String value) {
this.value = value;
this.count = 1;
}
public String getValue() {
return value;
}
public Integer getCount() {
return count;
}
public WordCount addCount() {
count++;
return this;
}
@Override
public int compareTo(WordCount o) {
int compareCount = count.compareTo(o.getCount());
return compareCount == 0 ? value.compareTo(o.getValue()) : compareCount;
}
@Override
public String toString() {
return value + " - " + count;
}
}
Конструктор класса принимает минимальную длину слова и минимальную частоту (по вашему условию это 4 и 10). дальше все просто...