Java 如何在计算两个列表之间的重复值时短路?
我有两个列表,我需要最快的方法来计数/检查列表A中与列表B中的元素匹配的重复元素 例如,如果列表A是Java 如何在计算两个列表之间的重复值时短路?,java,list,java-8,java-stream,Java,List,Java 8,Java Stream,我有两个列表,我需要最快的方法来计数/检查列表A中与列表B中的元素匹配的重复元素 例如,如果列表A是[“A”,“B”,“C”],而列表B是[“X”,“B”,“B”,“A”,“C”,“C”],我的计数器应该是2,因为在B中有两个重复的元素(“B”和“C”)。因为它是一个布尔方法,每当重复出现B中的A时,它都应该返回true 我正在避免级联循环,甚至尝试使用流。虽然下面的代码可以工作,但我仍然不能确定它的设计。 我现在就是这样做的: class MyPojo { int value; Str
[“A”,“B”,“C”]
,而列表B是[“X”,“B”,“B”,“A”,“C”,“C”]
,我的计数器应该是2,因为在B中有两个重复的元素(“B”和“C”)
。因为它是一个布尔方法,每当重复出现B中的A时,它都应该返回true
我正在避免级联循环,甚至尝试使用流。虽然下面的代码可以工作,但我仍然不能确定它的设计。
我现在就是这样做的:
class MyPojo {
int value; String str;
MyPojo(int value) { this.value = value; };
/* getters & setters*/
}
public static boolean hasDuplicates() {
List<Integer> forbiddenValues = Arrays.asList(1, 2, 3);
List<MyPojo> pojoList = Arrays.asList(new MyPojo(0), new MyPojo(2),
new MyPojo(2), new MyPojo(3), new MyPojo(3), new MyPojo(4));
for ( Integer value : forbiddenValues) {
long count = pojoList.stream()
.filter( pojoElement -> pojoElement.getValue() == value)
.count();
// returns true if in a single iteration count is greater than 1
if ( count > 1) {
return true;
}
}
return false;
}
类MyPojo{
int值;字符串str;
MyPojo(int-value){this.value=value;};
/*获取者和设置者*/
}
公共静态布尔值hasDuplicates(){
listForbiddenValues=Arrays.asList(1,2,3);
List-pojoList=Arrays.asList(新的MyPojo(0),新的MyPojo(2),
新MyPojo(2)、新MyPojo(3)、新MyPojo(3)、新MyPojo(4));
for(整数值:禁止值){
long count=pojoList.stream()
.filter(pojoElement->pojoElement.getValue()==value)
.count();
//如果单个迭代中的计数大于1,则返回true
如果(计数>1){
返回true;
}
}
返回false;
}
这将起作用
public static boolean hasDuplicates() {
List<MyPojo> forbiddenValues = Arrays.asList(new MyPojo(1), new MyPojo(2),
new MyPojo(3));
List<MyPojo> pojoList = Arrays.asList(new MyPojo(0), new MyPojo(2),
new MyPojo(2), new MyPojo(3), new MyPojo(3), new MyPojo(4));
for(MyPojo i : forbiddenValues){
if(pojoList.contains(i))
return true;
}
return false;
}
}
class MyPojo {
int value; String str;
MyPojo(int value) { this.value = value; };
public int getValue(){
return this.value;
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof MyPojo))
return false;
MyPojo p = (MyPojo) o;
return this.value==p.getValue();
}
}
public静态布尔hasdeplicates(){
listForbiddenValues=Arrays.asList(新的MyPojo(1),新的MyPojo(2),
新MyPojo(3));
List-pojoList=Arrays.asList(新的MyPojo(0),新的MyPojo(2),
新MyPojo(2)、新MyPojo(3)、新MyPojo(3)、新MyPojo(4));
for(MyPojo i:禁止值){
if(pojoList.contains(i))
返回true;
}
返回false;
}
}
MyPojo类{
int值;字符串str;
MyPojo(int-value){this.value=value;};
public int getValue(){
返回此.value;
}
@凌驾
公共布尔等于(对象o){
如果(o==这个)
返回true;
如果(!(MyPojo的o实例))
返回false;
MyPojo p=(MyPojo)o;
返回此.value==p.getValue();
}
}
这对您很有用。让我知道你有任何问题。如果需要,也可以使用并行流
使用流API
public静态布尔hasdeplicates(){
listForbiddenValues=Arrays.asList(1,2,3);
List-pojoList=Arrays.asList(新的MyPojo(0),新的MyPojo(2),
新MyPojo(2)、新MyPojo(3)、新MyPojo(3)、新MyPojo(4));
long count=pojoList.stream()
.filter(pojo->forbiddenValues.contains(pojo.getValue()))
.map(MyPojo::getValue)
.collect(收集器.groupingBy(值->值))
.values()
.stream()
.filter(值->值.size()>1)
.count();
返回计数>1;
}
没有流
public静态布尔hasdeplicates(){
listForbiddenValues=Arrays.asList(1,2,3);
List-pojoList=Arrays.asList(新的MyPojo(0),新的MyPojo(2),
新MyPojo(2)、新MyPojo(3)、新MyPojo(3)、新MyPojo(4));
映射计数=新的HashMap();
for(整数禁止:禁止值){
计数。放置(禁止,0);
}
for(MyPojo MyPojo:pojoList){
if(counts.containsKey(myPojo.getValue())){
int count=counts.get(myPojo.getValue());
如果(计数=1){
返回true;
}
counts.put(myPojo.getValue(),count+1);
}
}
返回false;
}
我建议使用纯命令式循环而不是流,因为后者往往会导致比您想象的更多的开销
所以,在这种情况下,我会先从嵌套for each循环开始,然后再考虑流
此外,如果您决定继续使用流方法,您可以做的一个改进是在计数之前调用limit(2)
,以便尽可能短路。公共静态布尔hasdeplicates(){
public static boolean hasDuplicates() {
List<Integer> forbiddenValues = Arrays.asList(1, 2, 3);
List<MyPojo> pojoList = Arrays.asList(new MyPojo(0), new MyPojo(2),
new MyPojo(2), new MyPojo(3), new MyPojo(3),
new MyPojo(4));
Map<Integer, Long> map =
pojoList.stream().collect(Collectors.groupingBy(MyPojo::getValue,
Collectors.counting()));
boolean result =
forbiddenValues.stream().filter(map::containsKey).map(map::get)
.anyMatch(count -> count > 1);
return result;
}
listForbiddenValues=Arrays.asList(1,2,3);
List-pojoList=Arrays.asList(新的MyPojo(0),新的MyPojo(2),
新MyPojo(2)、新MyPojo(3)、新MyPojo(3),
新MyPojo(4));
地图=
pojoList.stream().collect(收集器.groupingBy(MyPojo::getValue),
收集器。计数();
布尔结果=
禁止值.stream().filter(map::containsKey).map(map::get)
.anyMatch(计数->计数>1);
返回结果;
}
使用HashSet
检查元素是否存在,因为包含的
要快得多,按照@Aonimé的建议,您可以这样做
public static boolean hasDuplicates() {
List<Integer> forbiddenValues = Arrays.asList(1, 2, 3);
Set<Integer> forbiddenValuesSet = new HashSet<>(forbiddenValues);
List<MyPojo> pojoList = Arrays.asList(new MyPojo(0), new MyPojo(2),
new MyPojo(2), new MyPojo(3), new MyPojo(3), new MyPojo(4));
long count = pojoList.stream()
.filter(t -> forbiddenValuesSet.contains(t.value)).limit(2).count();
return count > 1;
}
public静态布尔hasdeplicates(){
listForbiddenValues=Arrays.asList(1,2,3);
设置禁止值Set=新哈希集(禁止值);
List-pojoList=Arrays.asList(新的MyPojo(0),新的MyPojo(2),
新MyPojo(2)、新MyPojo(3)、新MyPojo(3)、新MyPojo(4));
long count=pojoList.stream()
.filter(t->禁止值set.contains(t.value)).limit(2.count();
返回计数>1;
}
您可以使用
return pojoList.stream()
.map(MyPojo::getValue)
.filter(forbiddenValues::contains)
.collect(Collectors.toMap(Function.identity(), value -> false, (a, b) -> true))
.containsValue(true);
- 首先,将
MyPojo
元素映射到值
- 然后只让那些包含在
禁止值中的值通过(为了提高效率,强烈建议在集合变得更大时使用集合)
- 使用值作为键收集到映射,并最初映射到
false
,但使用合并函数,如果出现重复键,该函数将计算为true
- 如果生成的映射包含任何
true
值,则我们有duplica
public static boolean hasDuplicates() {
List<Integer> forbiddenValues = Arrays.asList(1, 2, 3);
Set<Integer> forbiddenValuesSet = new HashSet<>(forbiddenValues);
List<MyPojo> pojoList = Arrays.asList(new MyPojo(0), new MyPojo(2),
new MyPojo(2), new MyPojo(3), new MyPojo(3), new MyPojo(4));
long count = pojoList.stream()
.filter(t -> forbiddenValuesSet.contains(t.value)).limit(2).count();
return count > 1;
}
return pojoList.stream()
.map(MyPojo::getValue)
.filter(forbiddenValues::contains)
.collect(Collectors.toMap(Function.identity(), value -> false, (a, b) -> true))
.containsValue(true);
Set<Integer> seen = new HashSet<>();
for(MyPojo pojo: pojoList) {
Integer value = pojo.getValue();
if(forbiddenValues.contains(value) && !seen.add(value)) return true;
}
return false;