Java 项目数超过700000的频率列表(ArrayList或LinkedList)

Java 项目数超过700000的频率列表(ArrayList或LinkedList),java,linked-list,Java,Linked List,我有一个包含Person数据类型元素的列表。找到列表中每个元素的频率的最佳方法是什么,并且减少时间消耗 我尝试过以下方法,在i7、8GB上的时间超过10分钟 ArrayList<String> frequent = new ArrayList<>(); for (Person E: myList2) { int frequency = 0; //int frequency = Collections.frequen

我有一个包含Person数据类型元素的列表。找到列表中每个元素的频率的最佳方法是什么,并且减少时间消耗

我尝试过以下方法,在i7、8GB上的时间超过10分钟

    ArrayList<String> frequent = new ArrayList<>();

    for (Person E: myList2)
    {
        int frequency = 0;
        //int frequency = Collections.frequency(myList2, E); 

        for (Person e : myList2)
        {
            if (E.getPassName().equals(e.getPassName()))
                frequency++;
        }
        if (frequency >= times)
            frequent.add(E.getPassName());
    }
ArrayList frequency=new ArrayList();
对于(个人E:myList2)
{
整数频率=0;
//int frequency=Collections.frequency(myList2,E);
对于(个人e:myList2)
{
如果(E.getPassName().equals(E.getPassName()))
频率++;
}
如果(频率>=次)
frequency.add(例如getPassName());
}
此外,即使LinkedList中存在重复项,集合的结果始终为值1。

使用
映射存储频率:

Map<Person, Integer> frequency = new HashMap<Person, Integer>();

for (Person person: myList2) {
    if (frequency.containsKey(person)) {
        frequency.put(person, frequency.get(person) + 1);
    } else {
        frequency.put(person, 1);
    }
}

您的算法是
O(n^2)
。这很糟糕。使用
Collections.frequency
无法解决这一问题,它只是在传入的
Collection
上循环检查
是否等于
。也不要用那个

在Java 8中使用
映射

final Map<Person, Integer> count = myList2.stream()
        .collect(HashMap::new, (map, i) -> {
    map.merge(i, 1, Integer::sum);
}, HashMap::putAll);

Collections.frequency()
返回1,因为它将每个项目与
E
进行比较,而不是将每个项目的
passName
E
passName
进行比较?如果equals()正确,Collections.frequency应该执行您想要的操作。您可以在自己的实现中执行自定义equals。将此移动到Person.equals();那么,有什么更好的方法吗?@user3337714正如我所说:亲自重写equals()。当您执行此操作时:同时更新hashCode()@user3337714我确实会覆盖,但Collections.frequency不起作用:(frequency.contains或frequency.containskey//frequency.containsValuePerson包含各种其他数据,这将是唯一的。我只想比较Person.getPassName()@user3337714您需要覆盖
equals()
hashCode()
在您的
Person
类中,基于
passName
压缩对象。并使用上述相同的代码或对其进行任何更改。对不起,我是Java新手。@user3337714使用相同的代码。基本上
Map
使用
hashCode
equals
方法查找bucket中的元素。我想比较Person的名称,即Person.getName()而不是person对象本身。person对象包含我不想解释的其他变量。您认为我可以实现什么?@user3337714如果两个具有相同
密码的人可以被视为相等,那么按照我的建议正确地实现
等于
hashCode
。否则,请使用
 映射
并将
Person::getPassName
而不是Person放入
映射
final Map<Person, Integer> count = myList2.stream()
        .collect(HashMap::new, (map, i) -> {
    map.merge(i, 1, Integer::sum);
}, HashMap::putAll);
final Map<Person, Integer> count = new HashMap<>();
for (final Person person : myList2) {
    final Integer c = count.get(person);
    if (c != null) {
        count.put(person, c + 1);
    } else {
        count.put(person, 1);
    }
}
@Override
public int hashCode() {
    int hash = 3;
    hash = 89 * hash + Objects.hashCode(this.passName);
    return hash;
}

@Override
public boolean equals(Object obj) {
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }
    final Person other = (Person) obj;
    if (!Objects.equals(this.passName, other.passName)) {
        return false;
    }
    return true;
}