一个简单的问题,但无法在谷歌上找到答案。由于我通常使用SQL,因此我习惯于访问基于集合的操作,如下所示:
select Q, qCount
from (
select Q, qCount, min(qCount) over () as minQCount
from (
select Q, count(*) as qCount
from table_A
group by Q
)
)
where qCount = minQCount
这会从表中查找Q中所有不同Q值中基数最低的值。
对于Java List,是否有一种既定的有效方法?说:
List<Q> listOfQ //gets populated with different objects of Q
//objects of Q can represent the same value through an overridden equals()
//get each object from Q for which the cardinality of the value it represents
//is the lowest amongst the distinct values in the list
一个简单的例子是:
List<Integer> list = new ArrayList<Integer>();
list.addAll(Arrays.asList(new Integer[] {1,1,1,2,2,3,3,3,4,4,4,4,5,5}));
//want to retrieve {2,2,5,5}
//would also be nice to easily retrieve a map with {k:2 v:2, k:5 v:2}
//this being the equivalent of the SQL query above
谢谢!
答案 0 :(得分:4)
考虑使用GUAVA的Multiset。
在它上面,您可以使用count(key)
方法
答案 1 :(得分:1)
private static <K> Map<K, Integer> getElementsWithLessCardinality(
List<K> list) {
Map<K, Integer> map = new TreeMap<K, Integer>(); //or HashMap
Map<K, Integer> res = new TreeMap<K, Integer>();
Integer min = null;
for (K listElem : list) {
if (map.containsKey(listElem)) {
map.put(listElem, map.get(listElem) + 1);
} else {
map.put(listElem, 1);
}
}
for (Entry<K, Integer> pair : map.entrySet()) {
K key = pair.getKey();
Integer value = pair.getValue();
if (min == null) {
// Initial state
min = value;
res.put(key, value);
} else if (min.equals(pair.getValue())) {
res.put(key, value);
} else if (value.compareTo(min) == -1) {
res.clear();
min = value;
res.put(key, value);
}
}
return res;
}
我认为你可以这样做:
- 首先你得到一张地图。
- 然后你找到基数较少的那些并把它放在另一张地图上。
请注意,此解决方案使用参数类型,因此您可以在需要计算任何类型的对象时使用它。 (但要确保compareTo(),equals()和hashCode()在类K中得到很好的实现)
答案 2 :(得分:1)
使用apache commons集合:
final List<Integer> list = Arrays.asList(new Integer[]{1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5});
final Map<Integer, Integer> cardinalityMap = CollectionUtils.getCardinalityMap(list);
final int minCardinality = Collections.min(cardinalityMap.values());
System.out.println("min cardinality: " + minCardinality);
for (final Map.Entry<Integer, Integer> entry: cardinalityMap.entrySet()) {
if (minCardinality == entry.getValue()) {
System.out.println("key: " + entry.getKey());
}
}
控制台输出:
min cardinality: 2
key: 2
key: 5