有没有通用的方法来获取 Java 中两个列表的交集?
Is there a generic way to get the intersection of two lists in Java?
在 Java 中是否有获取两个列表交集的通用方法?
我想要一个方法,无论列表中的元素是 String、Long、Integer 还是 BigDecimal 类型,都可以找到包含在 list1 和 list2 中的元素。
我尝试用下面的代码来实现这个,在两个参数都包含相同类型的元素之前它工作正常,否则它 returns 在运行时是一个空列表。
private <T> List<T> intersect(List<T> list1, List<T> list2) {
List<T> list = new ArrayList<T>();
System.out.println("list1= "+list1);
System.out.println("list2= "+list2);
for (T t2 : list2) {
System.out.println("t2= "+t2 + ", class: " + t2.getClass());
}
for (T t : list1) {
System.out.println("t= "+t + ", class: " + t.getClass());
if(list2.contains(t)) {
System.out.println("list2 containts t");
list.add(t);
}
}
System.out.println("list= "+list);
return list;
}
调用相交方法的代码:
import javax.ws.rs.core.Response;
public boolean process(Response response, List<Object> sentObjects) {
String body = response.readEntity(String.class);
....
List<Object> parsedResponse = parseJson(body);
List<Object> intersection = intersect(sentObjects, parsedResponse);
...
}
列表中包含不同类型元素的示例输出:
list1= [11190, 11191, 11213]
list2= [11190, 11191, 11213]
t2= 11190, class: class java.lang.Long
t2= 11191, class: class java.lang.Long
t2= 11213, class: class java.lang.Long
t= 11190, class: class java.math.BigDecimal
t= 11191, class: class java.math.BigDecimal
t= 11213, class: class java.math.BigDecimal
list= []
问题:有没有什么方法可以强制 list1 的类型 T 与 list2 的类型 T 相同而不明确说明确切类型?
也许你可以直接使用对象class。如果您只是使用对象 class 的子 classes。希望对你有帮助。
Collection.contains
的定义只允许使用相等来检查元素;不同 类 的实例通常不相等(例如 Long 零和 BigDecimal 零不相等;但是空 ArrayList 和空 LinkedList 是)。
为了解决这个问题,您需要使用比 equals 更通用的东西,比如 BiPredicate<T, T>
:
if(list2.stream().anyMatch(u -> biPredicate.apply(t, u))) {
您需要将 BiPredicate 作为参数传递给您的方法,例如
BiPredicate<Number, Number> biPredicate = (t, u) -> t.longValue() == u.longValue();
您可以 select 一种通用类型,所有元素都可以在检查相等性之前转换为该通用类型。 Object.equals()
方法依赖于实现,但它很少 returns true
用于不同类型的对象,尤其是当参数不是派生类型时。
在这种特殊情况下,常见类型似乎是 String
。即Long
、Integer
、BigDecimal
都可以一致地转换为字符串表示。
据推测,您正在使用的 String
对象是没有分隔符(千位等)的十进制数。如果是这种情况,您只需对数字类型调用 toString()
即可创建等效表示。否则,您可以使用适当配置的 NumberFormat
来匹配 String
元素的预期格式。
List<T> intersect(List<? extends T> t1, Collection<?> t2) {
Set<String> tmp = t2.stream().map(Object::toString).collect(Collectors.toSet());
return t1.stream()
.filter(e -> tmp.contains(e.toString()))
.collect(Collectors.toList());
}
在 Java 中是否有获取两个列表交集的通用方法?
我想要一个方法,无论列表中的元素是 String、Long、Integer 还是 BigDecimal 类型,都可以找到包含在 list1 和 list2 中的元素。
我尝试用下面的代码来实现这个,在两个参数都包含相同类型的元素之前它工作正常,否则它 returns 在运行时是一个空列表。
private <T> List<T> intersect(List<T> list1, List<T> list2) {
List<T> list = new ArrayList<T>();
System.out.println("list1= "+list1);
System.out.println("list2= "+list2);
for (T t2 : list2) {
System.out.println("t2= "+t2 + ", class: " + t2.getClass());
}
for (T t : list1) {
System.out.println("t= "+t + ", class: " + t.getClass());
if(list2.contains(t)) {
System.out.println("list2 containts t");
list.add(t);
}
}
System.out.println("list= "+list);
return list;
}
调用相交方法的代码:
import javax.ws.rs.core.Response;
public boolean process(Response response, List<Object> sentObjects) {
String body = response.readEntity(String.class);
....
List<Object> parsedResponse = parseJson(body);
List<Object> intersection = intersect(sentObjects, parsedResponse);
...
}
列表中包含不同类型元素的示例输出:
list1= [11190, 11191, 11213]
list2= [11190, 11191, 11213]
t2= 11190, class: class java.lang.Long
t2= 11191, class: class java.lang.Long
t2= 11213, class: class java.lang.Long
t= 11190, class: class java.math.BigDecimal
t= 11191, class: class java.math.BigDecimal
t= 11213, class: class java.math.BigDecimal
list= []
问题:有没有什么方法可以强制 list1 的类型 T 与 list2 的类型 T 相同而不明确说明确切类型?
也许你可以直接使用对象class。如果您只是使用对象 class 的子 classes。希望对你有帮助。
Collection.contains
的定义只允许使用相等来检查元素;不同 类 的实例通常不相等(例如 Long 零和 BigDecimal 零不相等;但是空 ArrayList 和空 LinkedList 是)。
为了解决这个问题,您需要使用比 equals 更通用的东西,比如 BiPredicate<T, T>
:
if(list2.stream().anyMatch(u -> biPredicate.apply(t, u))) {
您需要将 BiPredicate 作为参数传递给您的方法,例如
BiPredicate<Number, Number> biPredicate = (t, u) -> t.longValue() == u.longValue();
您可以 select 一种通用类型,所有元素都可以在检查相等性之前转换为该通用类型。 Object.equals()
方法依赖于实现,但它很少 returns true
用于不同类型的对象,尤其是当参数不是派生类型时。
在这种特殊情况下,常见类型似乎是 String
。即Long
、Integer
、BigDecimal
都可以一致地转换为字符串表示。
据推测,您正在使用的 String
对象是没有分隔符(千位等)的十进制数。如果是这种情况,您只需对数字类型调用 toString()
即可创建等效表示。否则,您可以使用适当配置的 NumberFormat
来匹配 String
元素的预期格式。
List<T> intersect(List<? extends T> t1, Collection<?> t2) {
Set<String> tmp = t2.stream().map(Object::toString).collect(Collectors.toSet());
return t1.stream()
.filter(e -> tmp.contains(e.toString()))
.collect(Collectors.toList());
}