假设我有一个很大(> 100,000,000)的 Person ArrayList,其中 Person 定义为:
class Person {
public int id;
public String name;
}
我正在尝试编写一个方法,如果包含具有相同 ID 但不同名称的元素hasDuplicatePersonsWithDifferentNames()
,则返回该方法。例如:true
ArrayList
这将返回 true,因为有两个具有不同名称的相同 id
ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person(1, "bob");
people.add(new Person(1, "alice");
这将返回 false,因为虽然有两个相同的 id,但它们共享相同的名称
ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person(1, "bob");
people.add(new Person(1, "bob");
我在想会有一些方法可以利用 Java Streams,众所周知,Java Streams 是高效的,甚至可能是并发性的。但我找不到任何一个例子。我知道我可以使用字典并在O(n)
时间/空间中解决这个问题,但我相信使用流/并发我可以节省空间复杂性。
问题是你那种错误的数据结构。
如果您使用列表,则在列表中搜索某些内容涉及迭代列表。在您的情况下,这意味着(可能)测试列表中的每个元素。全部 1 亿。
使用流或并发将无济于事。您的代码仍然需要测试 1 亿个条目。(好吧,并行搜索可以为您提供 1P
倍的加速,P
可用物理内核的数量在哪里。但P
将是小而恒定的。)
所以如果你想做得比O(N)
......哪里N
是一个非常大的数字......你需要一个支持基于元素字段查找的数据结构。这里有一些可能性:
使用 aMap<Integer, Person>
并将其填充为从id
to的映射Person
。问题是 aMap
只能为每个键保存一个值,因此您实际上无法同时将 Bob 和 Alice 存储在映射中。(但这可能是比您目前正在做的更好的解决方案。)
你使用它HashMap
,像插入删除和查找这样的操作是O(1)
。
使用多地图。Apache Commons 和 Guava 都提供多地图类,或者您可以使用Map<Integer, List<Person>>
.
以上两者使用的内存都比ArrayList
. 另一种选择是使列表id
按Person
对象的值排序,以便您可以执行二进制搜索。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句