我想要一个可以计算我拥有的对象数量的类 - 听起来收集所有对象然后对它们进行分组会更有效。
Python在collections.Counter中有一个理想的结构,Java或Scala有类似的类型吗?
答案 0 :(得分:13)
来自您关联的文档:
Counter类与其他语言的bag或multisets相似。
Java没有Multiset
类或类似物。 Guava有一个MultiSet
集合,可以完全按照您的要求进行操作。
在纯Java中,您可以使用Map<T, Integer>
和新的merge
方法:
final Map<String, Integer> counts = new HashMap<>();
counts.merge("Test", 1, Integer::sum);
counts.merge("Test", 1, Integer::sum);
counts.merge("Other", 1, Integer::sum);
counts.merge("Other", 1, Integer::sum);
counts.merge("Other", 1, Integer::sum);
System.out.println(counts.getOrDefault("Test", 0));
System.out.println(counts.getOrDefault("Other", 0));
System.out.println(counts.getOrDefault("Another", 0));
输出:
2
3
0
您可以在class
中将这种行为包含在几行代码中:
public class Counter<T> {
final Map<T, Integer> counts = new HashMap<>();
public void add(T t) {
counts.merge(t, 1, Integer::sum);
}
public int count(T t) {
return counts.getOrDefault(t, 0);
}
}
像这样使用:
final Counter<String> counts = new Counter<>();
counts.add("Test");
counts.add("Test");
counts.add("Other");
counts.add("Other");
counts.add("Other");
System.out.println(counts.count("Test"));
System.out.println(counts.count("Other"));
System.out.println(counts.count("Another"));
输出:
2
3
0
答案 1 :(得分:9)
据我所知。但scala非常富有表现力,允许你自己做类似的东西:
def counts[T](s: Seq[T]) = s.groupBy(x => x).mapValues(_.length)
编辑:更简洁:
def counts[T](s: Seq[T]) = s.groupBy(identity).mapValues(_.length)
答案 2 :(得分:4)
另一个scala版本,一次完成并避免.groupBy
val l = List("a", "b", "b", "c", "b", "c", "b", "d")
l.foldLeft(Map[String, Int]() withDefaultValue (0))
{ (m, el) => m updated (el, m(el)+1)}
//> res1: Map(a -> 1, b -> 4, c -> 2, d -> 1)
或者如果您不想要一张默认值为零的地图
l.foldLeft(Map[String, Int]()) { (m, el) => m updated (el, m.getOrElse(el,0)+1)}
答案 3 :(得分:2)
大多数情况下,你应该把链接在一起的基本操作做好。像:
val s = Seq("apple", "oranges", "apple", "banana", "apple", "oranges", "oranges")
s.groupBy(l => l).map(t => (t._1, t._2.length)) //1
s.count(_ == "apple") //2
结果:
Map(banana -> 1, oranges -> 3, apple -> 3) //1 - result
3 //2 - result
答案 4 :(得分:0)
Guava MultiSet有一个计数方法
答案 5 :(得分:0)
在我最初提出这个问题很多年后,我意识到它是多么微不足道。我的超基本Scala解决方案是:
import scala.collection.mutable
/**
* Created by salim on 3/10/2017.
*/
case class Counter[T]() {
lazy val state:mutable.Map[T,Int] = mutable.HashMap[T,Int]()
def apply(i:T):Int = state.getOrElse(i,0)
def count(i:T):Unit = {
val newCount = 1 + this(i)
state += (i -> newCount)
}
}
答案 6 :(得分:0)
这是我使用可变映射的尾递归Scala实现
def counter[T](s: Seq[T]) = {
import scala.collection.mutable.Map
def counter_iter[T](s: Seq[T], m: Map[T, Int]): Map[T, Int]= {
if (s.isEmpty) m
else {
m(s.head) += 1
counter_iter(s.tail, m)
}
}
counter_iter(s, Map[T, Int]().withDefaultValue(0))
}
使用:
scala> counter(List(1,1,2,2,2,3,4))
res34: scala.collection.mutable.Map[Int,Int] = Map(2 -> 3, 4 -> 1, 1 -> 2, 3 -> 1)