Guava SortedSetMultimap 不会放置无序值
Guava SortedSetMultimap doesn't put unordered values
我想创建一个 TreeMultimap,但只有第一个值被添加为值。这是我的代码:
SortedSetMultimap<Double, String> sorted = TreeMultimap.create(
(o1, o2) -> o2.compareTo(o1),
(o1, o2) -> 0
);
allSuperSkuRepository.getAllSkuTitles().forEach(v -> {
String sku = v.getSkuTitle().split(" - ")[0];
Double lev = (double) levensteinDistance.getDistance(in, sku);
if (lev.compareTo(0.3) > 0) lev = .5; // just for testing
if (lev.compareTo(0.49) > 0) {
log.debug(lev);
log.debug(sku);
sorted.put(lev, sku);
}
});
log.debug(sorted); // {0.5=[s0104]}
如代码中所述,log.debug(sorted)
仅产生 {0.5=[s0104]},但预期结果将是 {0.5=[s0104, msr01, msr01-set]}
.
log.debug(lev), log.debug(sku)
正在输出预期值。
我需要更改什么才能在我的 Multimap 中获取某个键的所有值?
我正在使用番石榴 19。
重要提示:
如果我将比较器重写为
SortedSetMultimap<Double, String> sorted = TreeMultimap.create(
(o1, o2) -> o2.compareTo(o1),
(o1, o2) -> o2.compareTo(o1)
);
实际上添加了所有值,但我不希望以任何方式对值进行排序 - 它们应该按插入顺序出现。
您传递给 TreeMultimap
工厂的值比较器表示所有值都相等:
(o1, o2) -> 0
因此,只保留第一个。正如 documentation 所说(强调我的):
Implementation of Multimap whose keys and values are ordered by their natural ordering or by supplied comparators. In all cases, this implementation uses Comparable.compareTo(T)
or Comparator.compare(T, T)
instead of Object.equals(java.lang.Object)
to determine equivalence of instances.
您真正想要的是自定义 Multimap
,因为 predefined combinations 的 none 符合您的用例:
SetMultimap<Double, String> sorted = Multimaps.newSetMultimap(
new TreeMap<>(),
LinkedHashSet::new);
TreeMap
将确保对键进行排序(使用它们的自然顺序),每个值集合的 LinkedHashSet
将简单地保留插入顺序,同时删除重复值。
如果您没有重复值,只需使用 ArrayList
代替:
Multimap<Double, String> sorted = Multimaps.newMultimap(
new TreeMap<>(),
ArrayList::new);
更新: Louis Wasserman 在评论中适当地建议使用 MultimapBuilder
fluent API 而不是创建 Multimap
规范:
Multimap<Double, String> sorted = MultimapBuilder.treeKeys().linkedHashSetValues().build();
或
Multimap<Double, String> sorted = MultimapBuilder.treeKeys().arrayListValues().build();
我想创建一个 TreeMultimap,但只有第一个值被添加为值。这是我的代码:
SortedSetMultimap<Double, String> sorted = TreeMultimap.create(
(o1, o2) -> o2.compareTo(o1),
(o1, o2) -> 0
);
allSuperSkuRepository.getAllSkuTitles().forEach(v -> {
String sku = v.getSkuTitle().split(" - ")[0];
Double lev = (double) levensteinDistance.getDistance(in, sku);
if (lev.compareTo(0.3) > 0) lev = .5; // just for testing
if (lev.compareTo(0.49) > 0) {
log.debug(lev);
log.debug(sku);
sorted.put(lev, sku);
}
});
log.debug(sorted); // {0.5=[s0104]}
如代码中所述,log.debug(sorted)
仅产生 {0.5=[s0104]},但预期结果将是 {0.5=[s0104, msr01, msr01-set]}
.
log.debug(lev), log.debug(sku)
正在输出预期值。
我需要更改什么才能在我的 Multimap 中获取某个键的所有值?
我正在使用番石榴 19。
重要提示:
如果我将比较器重写为
SortedSetMultimap<Double, String> sorted = TreeMultimap.create(
(o1, o2) -> o2.compareTo(o1),
(o1, o2) -> o2.compareTo(o1)
);
实际上添加了所有值,但我不希望以任何方式对值进行排序 - 它们应该按插入顺序出现。
您传递给 TreeMultimap
工厂的值比较器表示所有值都相等:
(o1, o2) -> 0
因此,只保留第一个。正如 documentation 所说(强调我的):
Implementation of Multimap whose keys and values are ordered by their natural ordering or by supplied comparators. In all cases, this implementation uses
Comparable.compareTo(T)
orComparator.compare(T, T)
instead ofObject.equals(java.lang.Object)
to determine equivalence of instances.
您真正想要的是自定义 Multimap
,因为 predefined combinations 的 none 符合您的用例:
SetMultimap<Double, String> sorted = Multimaps.newSetMultimap(
new TreeMap<>(),
LinkedHashSet::new);
TreeMap
将确保对键进行排序(使用它们的自然顺序),每个值集合的 LinkedHashSet
将简单地保留插入顺序,同时删除重复值。
如果您没有重复值,只需使用 ArrayList
代替:
Multimap<Double, String> sorted = Multimaps.newMultimap(
new TreeMap<>(),
ArrayList::new);
更新: Louis Wasserman 在评论中适当地建议使用 MultimapBuilder
fluent API 而不是创建 Multimap
规范:
Multimap<Double, String> sorted = MultimapBuilder.treeKeys().linkedHashSetValues().build();
或
Multimap<Double, String> sorted = MultimapBuilder.treeKeys().arrayListValues().build();