Java单词统计程序问题:行号记录错误与排序需求
Hey there! I see you're working on a Java program to count word occurrences and track the lines they appear on, but you've hit two snags. Let's work through them one by one and get your program running just right.
Problem 1: Duplicate Line Numbers Being Recorded
Right now, your code appends the line number every time a word appears, which is why "the" shows [1,1,2,2] instead of [1,2]. The fix here is to use a Set<Integer> to track line numbers for each word—since Sets automatically handle duplicates, we'll only keep unique line numbers for each word.
We'll change your linenumbertrack from a HashMap<String, String> to HashMap<String, Set<Integer>>, then update the countwords method to add line numbers to the Set instead of concatenating strings.
Problem 2: Sorting Results by Occurrence Count (and Alphabetically When Counts Match)
Your current output is in arbitrary order from the HashMap's keySet. To sort first by count descending, then by word ascending, we'll extract the entries from the count map, sort them with a custom comparator, then iterate through the sorted list.
Full Modified Code
package test; import java.util.*; public class Countcharacters { static HashMap<String, Integer> countcharact = new HashMap<>(); static HashMap<String, Set<Integer>> linenumbertrack = new HashMap<>(); static int count = 1; static void countwords(String line) { String[] input = line.split("\\s"); for (String word : input) { // Update word count (simplified with getOrDefault) countcharact.put(word, countcharact.getOrDefault(word, 0) + 1); // Add current line number to the word's unique line set linenumbertrack.computeIfAbsent(word, k -> new HashSet<>()).add(count); } count++; } public static void main(String[] args) { String inp = "the quick brown fox jumped over the lazy dog's bowl.\nthe dog was angry with the fox for considering him lazy."; String[] lines = inp.split("\n"); for (String line : lines) { Countcharacters.countwords(line); } // Convert map entries to a list for sorting List<Map.Entry<String, Integer>> wordList = new ArrayList<>(countcharact.entrySet()); // Custom sort: first by count descending, then by word ascending wordList.sort((entry1, entry2) -> { int countCompare = entry2.getValue().compareTo(entry1.getValue()); if (countCompare != 0) { return countCompare; } return entry1.getKey().compareTo(entry2.getKey()); }); // Print sorted results with ordered line numbers for (Map.Entry<String, Integer> entry : wordList) { String word = entry.getKey(); int occurrence = entry.getValue(); Set<Integer> linesSet = linenumbertrack.get(word); // Sort line numbers for consistent output List<Integer> sortedLines = new ArrayList<>(linesSet); Collections.sort(sortedLines); System.out.println(word + " " + occurrence + " " + sortedLines); } } }
Key Changes Explained
Line Number Tracking:
- Switched
linenumbertrackto useSet<Integer>to automatically eliminate duplicate line numbers. - Used
computeIfAbsentto create a new Set for a word if it doesn't exist, then added the current line number to the Set.
- Switched
Sorting:
- Converted the HashMap's entrySet to an ArrayList so we can apply custom sorting.
- The comparator first compares word counts in descending order. If counts are equal, it sorts words alphabetically in ascending order.
- Converted the line number Set to a sorted list before printing, so line numbers appear in numerical order (e.g.,
[1,2]instead of[2,1]).
Updated Output
the 4 [1, 2] fox 2 [1, 2] angry 1 [2] bowl. 1 [1] brown 1 [1] considering 1 [2] dog 1 [2] dog's 1 [1] for 1 [2] him 1 [2] jumped 1 [1] lazy 1 [1] lazy. 1 [2] over 1 [1] quick 1 [1] was 1 [2] with 1 [2]
内容的提问来源于stack exchange,提问作者gamechanger17

