从Java List结构中选择具有最低基数的元素

时间:2015-04-30 19:19:21

标签: java list sorting collections

一个简单的问题,但无法在谷歌上找到答案。由于我通常使用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

谢谢!

3 个答案:

答案 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