Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:搜索对象数组列表以查找匹配ID但不同字段的有效方法_Java_Algorithm_Concurrency_Java Stream - Fatal编程技术网

Java:搜索对象数组列表以查找匹配ID但不同字段的有效方法

Java:搜索对象数组列表以查找匹配ID但不同字段的有效方法,java,algorithm,concurrency,java-stream,Java,Algorithm,Concurrency,Java Stream,假设我有一个较大(>100000000)的Person数组列表,其中Person的定义如下: class Person { public int id; public String name; } 我正在尝试编写一个方法,hasDuplicatePersonsWithDifferentNames(),如果ArrayList包含ID相同但名称不同的元素,则该方法返回true。例如: 这将返回true,因为有两个相同的ID具有不同的名称 ArrayList<Person>

假设我有一个较大(>100000000)的Person数组列表,其中Person的定义如下:

class Person {
    public int id;
    public String name;
}
我正在尝试编写一个方法,
hasDuplicatePersonsWithDifferentNames()
,如果
ArrayList
包含ID相同但名称不同的元素,则该方法返回
true
。例如:

这将返回true,因为有两个相同的ID具有不同的名称

ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person(1, "bob");
people.add(new Person(1, "alice");
ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person(1, "bob");
people.add(new Person(1, "bob");
ArrayList people=new ArrayList();
人员。添加(新人员(1,“bob”);
添加(新人物(1,“alice”);
这将返回false,因为虽然有两个相同的id,但它们共享相同的名称

ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person(1, "bob");
people.add(new Person(1, "alice");
ArrayList<Person> people = new ArrayList<Person>();
people.add(new Person(1, "bob");
people.add(new Person(1, "bob");
ArrayList people=new ArrayList();
人员。添加(新人员(1,“bob”);
人员。添加(新人员(1,“bob”);

我在想会有一些方法来利用Java流,这是众所周知的高效方法,甚至可能是并发方法。但我找不到这两种方法的示例。我知道我可以使用字典在
O(n)中解决这个问题
时间/空间,但我相信使用streams/concurrency可以节省空间复杂性。

问题在于您使用了错误的数据结构

如果你使用一个列表,那么搜索列表中的内容就需要迭代列表。在你的例子中,这意味着(可能)测试列表中的每个元素。所有1亿个元素

使用流或并发不会有帮助。您的代码仍然需要测试1亿个条目。(好的,并行搜索可以给您一个
p
倍的速度,其中
p
是可用的物理核心数。但是
p
将是一个小而恒定的过程。)

因此,如果您想做得比
O(N)
…更好,
N
是一个非常大的数字…您需要一个支持基于元素字段的查找的数据结构。以下是一些可能性:

  • 使用
    Map
    并将其填充为从
    id
    Person
    的映射。问题是
    Map
    只能为每个键保存一个值,因此无法同时在映射中存储Bob和Alice。(但这可能是一个比当前更好的解决方案。)

    如果使用
    HashMap
    ,则插入、删除和查找等操作都是
    O(1)

  • 使用多重映射。Apache Commons和Guava都提供多重映射类,或者您可以使用
    map

  • 上述两种方法使用的内存都比
    ArrayList
    多得多。另一种方法是根据
    Person
    对象的
    id
    值对列表进行排序,以便执行二进制搜索


基于您已共享的架构,如果您为此对象覆盖了适当的
equals
hashCode
。您可以将数据转换为哈希集,并比较初始列表和最终集的大小。如果没有,则可以使用
映射
,其中
id
作为键,
name
s作为值,当y如果在映射中找到一个现有的键,则返回
true
。在
O(n)
运行时以下的时间内无法解决此问题,因为最坏的情况是(将迭代中的第一个和最后一个元素视为重复)。有了并发性,您可能唯一希望的就是分布式执行。您可以尝试
toConcurrentMap
,将ID映射到键,将名称映射到值,并使用一个合并函数比较旧值和新值。如果它们相同,则将假原子布尔值设置为真。最后,检查原子布尔值是否正确olean。缺点是,这不是短路……当你想节省空间时,你必须放弃时间。使用考虑id和名称的比较器对列表进行排序。之后,你只需再次检查列表,并将一个元素与下一个元素进行比较。固定空间,但O(n log(n))时间。(请添加更多上下文:如果一开始就没有理由为一个ID使用多个名称,最好使用
集合而不是
列表,除非需要索引访问。)