按值排序 Hashmap,然后按字母顺序排序
Sort Hashmap by value and then alphabetically
我正在创建一个词频程序,它可以很好地计算单词数。我正在使用哈希图来存储词频。我使用单词作为键,计数作为值。但是,我想先按词频对末尾的 hashMap 进行排序,然后按字母顺序键进行排序,如下所示:
it - 2
of - 2
the - 2
times- 2
was - 2
best- 1
worst - 1
我猜我需要一个自定义比较器,但我不知道如何构造它。请问,有什么建议吗?
鉴于您只需要执行一次这种排序,我建议您创建一个 Result
对象来保存您的 String
和 Integer
值并实现 Comparable
(保持密钥相同)。当您需要对结果进行排序时,只需在 HashMap
上调用 values()
,然后对它们进行排序。
Main.java
import java.util.*;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
HashMap<String, Result> hm = new HashMap<String, Result>();
addTo(hm, "to");
addTo(hm, "be");
addTo(hm, "or");
addTo(hm, "not");
addTo(hm, "to");
addTo(hm, "be");
List<Result> results = new ArrayList(hm.values());
Collections.sort(results);
for(Result result : results)
{
System.out.println(result.getValue() + " - " +result.getCount());
}
}
public static void addTo(HashMap<String, Result> hm, String entry)
{
if(! hm.containsKey(entry))
{
Result result = new Result(entry);
hm.put(entry, new Result(entry));
}
hm.get(entry).increment();
}
}
Result.java
public class Result implements Comparable
{
private int count;
private String value;
public Result(String value)
{
this.value = value;
this.count = 0;
}
public String getValue()
{
return value;
}
public int getCount()
{
return count;
}
public void increment()
{
count++;
}
@Override
public int compareTo(Object o)
{
Result result = (Result)o;
if(getCount() == result.getCount())
{
return getValue().compareTo(result.getValue());
}
else
{
// Want larger values to be on-top, so reverse traditional sort order
return ((Integer)result.getCount()).compareTo((Integer)getCount());
}
}
}
您不能排序 HashMap
,如 Javadoc:
中所述
... This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.
您必须将其放入一个不同的结构中,以保持您想要的顺序。
根据您提供的信息,您的订单似乎有几个标准:
- 按
Map.Entry
值 降序排列
- 按
Map.Entry
键升序排列
您可以使用 Stream
API,以及 Map.Entry
.
中有用的 Comparator
final HashMap<String, Integer> map = new HashMap<>();
map.put("it", 2);
map.put("of", 2);
map.put("the", 2);
map.put("times", 2);
map.put("was", 2);
map.put("best", 1);
map.put("worst", 1);
System.out.println("No Guaranteed Order:");
map.entrySet().stream()
.forEach(System.out::println);
System.out.println();
System.out.println("With Ordering:");
map.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue()
.reversed()
.thenComparing(Map.Entry.comparingByKey()))
.forEach(System.out::println);
输出:
No Guaranteed Order:
the=2
times=2
of=2
was=2
best=1
worst=1
it=2
With Ordering:
it=2
of=2
the=2
times=2
was=2
best=1
worst=1
我正在创建一个词频程序,它可以很好地计算单词数。我正在使用哈希图来存储词频。我使用单词作为键,计数作为值。但是,我想先按词频对末尾的 hashMap 进行排序,然后按字母顺序键进行排序,如下所示:
it - 2
of - 2
the - 2
times- 2
was - 2
best- 1
worst - 1
我猜我需要一个自定义比较器,但我不知道如何构造它。请问,有什么建议吗?
鉴于您只需要执行一次这种排序,我建议您创建一个 Result
对象来保存您的 String
和 Integer
值并实现 Comparable
(保持密钥相同)。当您需要对结果进行排序时,只需在 HashMap
上调用 values()
,然后对它们进行排序。
Main.java
import java.util.*;
class Main
{
public static void main (String[] args) throws java.lang.Exception
{
HashMap<String, Result> hm = new HashMap<String, Result>();
addTo(hm, "to");
addTo(hm, "be");
addTo(hm, "or");
addTo(hm, "not");
addTo(hm, "to");
addTo(hm, "be");
List<Result> results = new ArrayList(hm.values());
Collections.sort(results);
for(Result result : results)
{
System.out.println(result.getValue() + " - " +result.getCount());
}
}
public static void addTo(HashMap<String, Result> hm, String entry)
{
if(! hm.containsKey(entry))
{
Result result = new Result(entry);
hm.put(entry, new Result(entry));
}
hm.get(entry).increment();
}
}
Result.java
public class Result implements Comparable
{
private int count;
private String value;
public Result(String value)
{
this.value = value;
this.count = 0;
}
public String getValue()
{
return value;
}
public int getCount()
{
return count;
}
public void increment()
{
count++;
}
@Override
public int compareTo(Object o)
{
Result result = (Result)o;
if(getCount() == result.getCount())
{
return getValue().compareTo(result.getValue());
}
else
{
// Want larger values to be on-top, so reverse traditional sort order
return ((Integer)result.getCount()).compareTo((Integer)getCount());
}
}
}
您不能排序 HashMap
,如 Javadoc:
... This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.
您必须将其放入一个不同的结构中,以保持您想要的顺序。
根据您提供的信息,您的订单似乎有几个标准:
- 按
Map.Entry
值 降序排列 - 按
Map.Entry
键升序排列
您可以使用 Stream
API,以及 Map.Entry
.
Comparator
final HashMap<String, Integer> map = new HashMap<>();
map.put("it", 2);
map.put("of", 2);
map.put("the", 2);
map.put("times", 2);
map.put("was", 2);
map.put("best", 1);
map.put("worst", 1);
System.out.println("No Guaranteed Order:");
map.entrySet().stream()
.forEach(System.out::println);
System.out.println();
System.out.println("With Ordering:");
map.entrySet().stream()
.sorted(Map.Entry.<String, Integer>comparingByValue()
.reversed()
.thenComparing(Map.Entry.comparingByKey()))
.forEach(System.out::println);
输出:
No Guaranteed Order:
the=2
times=2
of=2
was=2
best=1
worst=1
it=2
With Ordering:
it=2
of=2
the=2
times=2
was=2
best=1
worst=1