从列表中查找最常见的对象
假设我有一个 Employee
对象的 List
。 Employee
对象有一个 getDepartment
方法,该方法返回一个 Department
对象。我想遍历该列表以找到拥有最多 Employee 的部门(即最常从 getDepartment 返回的 Department 对象)。最快的方法是什么?
public class Employee{
static allEmployees = new ArrayList<Employee>();
int id;
Department department;
public Employee(int id, Department department){
this.id = id;
this.department = department;
allEmployees.add(this);
}
public Department getDepartment(){
return department;
}
public static List<Employee> getAllEmployees(){
return allEmployees;
}
}
public class Department{
int id;
String name;
public Department(int id){
this.id = id;
}
public String getName(){
return name;
}
}
如果两个部门的员工人数相同,则返回哪个部门并不重要。
谢谢!
Let's say I have a List
of Employee
Objects. The Employee
Objects have a getDepartment
method which returns a Department
Object. I want to iterate through that list to find the department with the most Employee
s (i.e. the Department
Object returned most often from getDepartment
). What is the fastest way to do this?
public class Employee{
static allEmployees = new ArrayList<Employee>();
int id;
Department department;
public Employee(int id, Department department){
this.id = id;
this.department = department;
allEmployees.add(this);
}
public Department getDepartment(){
return department;
}
public static List<Employee> getAllEmployees(){
return allEmployees;
}
}
public class Department{
int id;
String name;
public Department(int id){
this.id = id;
}
public String getName(){
return name;
}
}
If there's two departments with an equal number of employees it doesn't matter which is returned.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
创建部门 ID 的地图 ->很重要。
这样你就可以通过 id 获得所有计数的集合。您还可以维护一个最大项,它是对具有最高计数的映射条目的引用。
该算法类似于:
1) 初始化一个 Map 和一个 currentMax
2)循环遍历员工
3)对于每个员工,获取其部门ID
4)执行类似map.get(currentId)的操作
a) 如果当前计数为空,则初始化它
5) 增加计数
6)如果增加的计数>; currentMax, update currentMax
该算法将在 O(n) 内运行;我认为你没有比这更好的了。它的空间复杂度也是 O(n),因为计数的数量与输入的大小成正比。
如果您愿意,您可以创建一个使用组合(即包含一个映射和一个列表)的类,并且还管理保留指向具有最高计数的条目的指针。这样你的这部分功能就被正确封装了。这种方法的更大好处是,它允许您在将项目输入到列表中时维护计数(您可以代理将员工添加到列表中的方法,以便他们更新地图计数器)。但可能有点矫枉过正。
create a map of department id -> counts.
that way you get a collection of all the counts by id. You can also maintain a max item that is a reference to the map entry with the highest count.
the algorithm would be something like:
1) Initialize a Map and a currentMax
2) loop through employees
3) for each employee, get its department id
4) do something like map.get(currentId)
a) if the current count is null, initialize it
5) increment the count
6) if the incremented count is > currentMax, update currentMax
This algorithm will run in O(n); I don't think you can get any better than that. Its space complexity is also O(n) because the number of counts is proportional to the size of the input.
If you wanted, you could create a class that uses composition (i.e. contains a Map and a List) and also manages keeping pointers to the Entry with the highest count. That way this part of your functionality is properly encapsulated. The stronger benefit of this approach is it allows you to maintain the count as you enter items into the list (you would proxy the methods that add employees to the list so they update the map counter). Might be overkill though.
这是一个普通的 Java 8 解决方案:
它最多遍历员工列表两次。如果您愿意添加第三方依赖项,则使用 jOOλ 的等效解决方案如下
:(免责声明:我在 jOOλ 背后的公司工作)
Here's a vanilla Java 8 solution:
It passes through the list of employees at most twice. An equivalent solution using jOOλ, if you're willing to add a third-party dependency, is this:
(Disclaimer: I work for the company behind jOOλ)
我会使用 Guava 执行类似的操作:
您需要正确实现
equals
和hashCode
在Department
上才能正常工作。这里还有一个问题提到了创建未来的“排行榜”类型 Multiset 将根据其包含的每个条目的数量来维护订单。
I would do something like this using Guava:
You would need a correct implementation of
equals
andhashCode
onDepartment
for this to work.There's also an issue here that mentions the possibility of creating a "leaderboard" type
Multiset
in the future that would maintain an order based on the count of each entry it contains.由于您只想统计员工数量,因此制作地图相对容易。
将部门映射到员工数量(您增加每个员工的计数)。或者,您可以使用列表将整个 Employee 存储在地图中:
并查看列表的大小。
如果你不知道如何使用该类,可以查看HashMap文档:
http://download.oracle.com/javase /1.4.2/docs/api/java/util/HashMap.html
提示:您需要使用 HashMap.keySet() 来查看已输入哪些部门。
Since you just want to count employees, it's relatively easy to make a map.
that maps Departments to the number of employees (you increment the count for every employee). Alternatively, you can store the whole Employee in the map with a list:
and look at the size of your lists instead.
Then you can look at the HashMap documentation if you don't know how to use the class:
http://download.oracle.com/javase/1.4.2/docs/api/java/util/HashMap.html
Hint: you will need to use HashMap.keySet() to see which departments have been entered.
我会这样做,modulo == null 和 isEmpty 检查:
还有 CollectionUtils.getCardinalityMap() 它将完成第一种方法的工作,但这更灵活更偏向番石榴。
请记住,C 类应该得到很好的实现,即具有 equals()、hashCode() 并实现 Comparable。
这是您可以使用它的方式:
作为奖励,您还可以使用类似的方法获取频率较低的元素,只需使用 Ordering.natural() 提供第一个方法并且不要反转它。
I would do it like that, modulo == null and isEmpty checks:
There is also CollectionUtils.getCardinalityMap() which will do the job of the first method, but this is more flexible and more guavish.
Just keep in mind that the C class should be well implemented, that is have equals(), hashCode() and implement Comparable.
This is how you can use it:
As a bonus, you can also get the less frequent element with a similar method, just, feed the first method with Ordering.natural() and do not reverse it.