TreeMap按值排序报错求助:自定义TreeSet排序实现异常
Hey Keith, let's break down why your code is throwing errors and get it working properly!
What's Wrong With the Original Code?
Your approach to use TreeSet<Map.Entry<Character, Integer>> to sort entries by value is on the right track, but there are two critical issues causing problems:
- Incomplete & Unsafe Comparator: Your
comparemethod is cut off (e1.getV...should bee1.getValue()) and doesn't handle cases where two entries have the same value. TreeSet uses thecompareresult to judge equality—ifcompare(e1,e2) == 0, it treats them as identical elements and won't store both, even if their keys are different. - Missing
@OverrideAnnotation: While not a compile error, skipping this annotation hides potential typos (like misspellingcompare) and makes the code harder to read.
Fixed Full Code
Here's the corrected version that sorts entries by value in descending order, and uses key sorting as a tiebreaker to avoid losing entries:
public class CharCountSorter { public static void main(String[] args) { String s = "yourInputStringHere"; StringBuilder sb = new StringBuilder(); Map<Character, Integer> map = new TreeMap<>(); // Count character occurrences for (char c : s.toCharArray()) { map.put(c, map.getOrDefault(c, 0) + 1); } // TreeSet with a proper comparator: sort by value descending, then key ascending TreeSet<Map.Entry<Character, Integer>> set = new TreeSet<>(new Comparator<Map.Entry<Character, Integer>>() { @Override public int compare(Map.Entry<Character, Integer> e1, Map.Entry<Character, Integer> e2) { // First compare values in reverse order int valueComparison = e2.getValue() - e1.getValue(); // If values are equal, compare keys to ensure uniqueness if (valueComparison == 0) { return e1.getKey().compareTo(e2.getKey()); } return valueComparison; } }); // Add all map entries to the TreeSet set.addAll(map.entrySet()); // Build the result string for (Map.Entry<Character, Integer> entry : set) { sb.append(entry.getKey()).append(": ").append(entry.getValue()).append(" "); } System.out.println(sb.toString().trim()); } }
Key Fixes Explained
- Tiebreaker for Equal Values: By adding the key comparison when values are the same, we ensure that even if two characters have the same count, they'll both be stored in the TreeSet (since their keys are different,
comparewon't return 0). - Complete Comparator Implementation: We finished the
getValue()call and added the@Overrideannotation to catch any mistakes during compilation. - Clear Logic: The comparator first prioritizes value sorting, then falls back to key sorting to maintain consistency with TreeSet's equality rules.
A Better Alternative (Optional)
Using TreeSet for sorting is valid, but if you don't need the automatic sorting behavior of a TreeSet (like dynamic insertion), a simpler approach is to convert the entry set to an ArrayList and sort it directly:
// Alternative: Use ArrayList + Collections.sort() List<Map.Entry<Character, Integer>> entryList = new ArrayList<>(map.entrySet()); Collections.sort(entryList, (e1, e2) -> { int valueComp = e2.getValue() - e1.getValue(); return valueComp == 0 ? e1.getKey().compareTo(e2.getKey()) : valueComp; });
This is more efficient for one-time sorting and avoids any confusion with TreeSet's uniqueness rules.
内容的提问来源于stack exchange,提问作者Keith

