使用 Java8 比较两种不同类型的列表
comparing two different type of List using Java8
class Person{
private String name;
private String address;
private int id;
private int uniqueIdentificationNumber;
}
class Company{
private String name;
private String address;
private int id;
private int uniqueIdentificationNumber;
private String company;
}
class Test{
public static void main(String[] args)
{
List<Person> persons = new ArrayList<>();
Person p1 = new Person();
p1.setName("ABC");
p1.setAddress("US");
p1.setId(1);
p1.setUniqueIdentificationNumber(11);
Person p2 = new Person();
p2.setName("PQR");
p2.setAddress("US");
p2.setId(2);
p2.setUniqueIdentificationNumber(22);
persons.add(p1);
persons.add(p2);
List<Company> companies = new ArrayList<>();
Company c1 = new Comapny();
c1.setName("ABC");
c1.setAddress("US");
c1.setId(3);
c1.setUniqueIdentificationNumber(44);
c1.setCompany("C1")
Company c2 = new Comapny();
c2.setName("ABC");
c2.setAddress("US");
c2.setId(1);
c2.setUniqueIdentificationNumber(11);
c2.setCompany("C2");
companies.add(c1);
companies.add(c2)
}
}
我想将两种不同对象类型的列表(公司和个人)与 Java8 流 API 和 return 客户进行比较与 Id 和 setUniqueIdentificationNumber 匹配的对象。即在这种情况下它应该重新调整 c2.
谁能帮忙解决这个问题
不清楚 Person
和 Company
中的 uniqueIdentificationNumber
是如何关联的。值得refine这些classes来更好地表示它们之间的关系(也许公司可以参考客户名单)。并且不要过度使用 setter,如果 id 是唯一的,则无需允许更改它。
尽管由于您的 class 设计存在缺陷,尚不清楚这些值是如何关联的,但在技术上是可行的。
return the customer object which is matching with Id
为此,您需要创建两个 映射,将这些 标识符 与 公司 和 人 。然后在其中一个 maps 的 keys 上创建一个流,并检查每个 key 是否包含在另一个 map 中。然后检索过滤键的 Person
对象并将结果收集到列表中。
Map<Integer, Person> personById =
persons.stream()
.collect(Collectors.toMap(Person::getUniqueIdentificationNumber,
Function.identity()));
Map<Integer, Company> companyById =
companies.stream()
.collect(Collectors.toMap(Company::getUniqueIdentificationNumber,
Function.identity()));
List<Person> customers =
personById.keySet().stream()
.filter(companyById::containsKey) // checking whether id is present in the company map
.map(personById::get) // retrieving customers
.collect(Collectors.toList());
更新
让我重新描述一下问题。
有两个不相关的 classes A
和 B
。两个 class 都有 两个 int
类型的字段 ,比方说 val1
和 val2
(也许还有几个字段,但我们对它们不感兴趣)。
我们有对象列表 A
和对象列表 B
。目标是找到一个对象 A
,其中存在一个对象 B
,val1
和 val2
具有相同的值(为了简单起见,我建议坚持这个例子)。
有两种方法可用于此目的:
- 创建一个具有两个字段
val1
和 val2
的辅助 class,并将 A
和 B
的每个实例与此 [= 的实例相关联105=];
- 创建一个嵌套映射
Map<Integer, Map<Integer, *targetClass*>>
,这个解决方案比较复杂且不太灵活,如果您需要按三个、四个等字段比较对象,代码将很快变得难以理解。
所以我会坚持使用第一种方法。我们需要声明 ValueHolder
class 两个字段,并根据这些字段实现 equals/hashCode
合约。对于 Java 16 及以上我们可以利用 record 并利用 equals()
, hashCode
, 编译器提供的getters。带有记录的选项将如下所示:
public record ValueHolder(int val1, int val2) {} // equals/hashCode, constructor and getters provided by the compiler
类 A
和 B
public class A {
private int val1;
private int val2;
// constructor and getters
}
public class B {
private int val1;
private int val2;
// constructor and getters
}
以及接受两个列表的方法:List<A>
和 List<B>
,以及 return 结果为 Optional<A>
。因为匹配元素可能存在也可能不存在,在这种情况下 return 一个可选对象是一个很好的做法,而不是 returning null
以防找不到结果。它提供了更大的灵活性,而这正是设计可选选项的原因。
public Optional<A> getMatchingItem(List<A> listA, List<B> listB) {
Map<ValueHolder, A> aByValue = listA.stream()
.collect(Collectors.toMap(a -> new ValueHolder(a.getVal1(), a.getVal2()),
Function.identity()));
Map<ValueHolder, B> bByValue = listB.stream()
.collect(Collectors.toMap(b -> new ValueHolder(b.getVal1(), b.getVal2()),
Function.identity()));
return aByValue.keySet().stream()
.filter(bByValue::containsKey)
.findFirst()
.map(aByValue::get);
}
class Person{
private String name;
private String address;
private int id;
private int uniqueIdentificationNumber;
}
class Company{
private String name;
private String address;
private int id;
private int uniqueIdentificationNumber;
private String company;
}
class Test{
public static void main(String[] args)
{
List<Person> persons = new ArrayList<>();
Person p1 = new Person();
p1.setName("ABC");
p1.setAddress("US");
p1.setId(1);
p1.setUniqueIdentificationNumber(11);
Person p2 = new Person();
p2.setName("PQR");
p2.setAddress("US");
p2.setId(2);
p2.setUniqueIdentificationNumber(22);
persons.add(p1);
persons.add(p2);
List<Company> companies = new ArrayList<>();
Company c1 = new Comapny();
c1.setName("ABC");
c1.setAddress("US");
c1.setId(3);
c1.setUniqueIdentificationNumber(44);
c1.setCompany("C1")
Company c2 = new Comapny();
c2.setName("ABC");
c2.setAddress("US");
c2.setId(1);
c2.setUniqueIdentificationNumber(11);
c2.setCompany("C2");
companies.add(c1);
companies.add(c2)
}
}
我想将两种不同对象类型的列表(公司和个人)与 Java8 流 API 和 return 客户进行比较与 Id 和 setUniqueIdentificationNumber 匹配的对象。即在这种情况下它应该重新调整 c2.
谁能帮忙解决这个问题
不清楚 Person
和 Company
中的 uniqueIdentificationNumber
是如何关联的。值得refine这些classes来更好地表示它们之间的关系(也许公司可以参考客户名单)。并且不要过度使用 setter,如果 id 是唯一的,则无需允许更改它。
尽管由于您的 class 设计存在缺陷,尚不清楚这些值是如何关联的,但在技术上是可行的。
return the customer object which is matching with Id
为此,您需要创建两个 映射,将这些 标识符 与 公司 和 人 。然后在其中一个 maps 的 keys 上创建一个流,并检查每个 key 是否包含在另一个 map 中。然后检索过滤键的 Person
对象并将结果收集到列表中。
Map<Integer, Person> personById =
persons.stream()
.collect(Collectors.toMap(Person::getUniqueIdentificationNumber,
Function.identity()));
Map<Integer, Company> companyById =
companies.stream()
.collect(Collectors.toMap(Company::getUniqueIdentificationNumber,
Function.identity()));
List<Person> customers =
personById.keySet().stream()
.filter(companyById::containsKey) // checking whether id is present in the company map
.map(personById::get) // retrieving customers
.collect(Collectors.toList());
更新
让我重新描述一下问题。
有两个不相关的 classes A
和 B
。两个 class 都有 两个 int
类型的字段 ,比方说 val1
和 val2
(也许还有几个字段,但我们对它们不感兴趣)。
我们有对象列表 A
和对象列表 B
。目标是找到一个对象 A
,其中存在一个对象 B
,val1
和 val2
具有相同的值(为了简单起见,我建议坚持这个例子)。
有两种方法可用于此目的:
- 创建一个具有两个字段
val1
和val2
的辅助 class,并将A
和B
的每个实例与此 [= 的实例相关联105=]; - 创建一个嵌套映射
Map<Integer, Map<Integer, *targetClass*>>
,这个解决方案比较复杂且不太灵活,如果您需要按三个、四个等字段比较对象,代码将很快变得难以理解。
所以我会坚持使用第一种方法。我们需要声明 ValueHolder
class 两个字段,并根据这些字段实现 equals/hashCode
合约。对于 Java 16 及以上我们可以利用 record 并利用 equals()
, hashCode
, 编译器提供的getters。带有记录的选项将如下所示:
public record ValueHolder(int val1, int val2) {} // equals/hashCode, constructor and getters provided by the compiler
类 A
和 B
public class A {
private int val1;
private int val2;
// constructor and getters
}
public class B {
private int val1;
private int val2;
// constructor and getters
}
以及接受两个列表的方法:List<A>
和 List<B>
,以及 return 结果为 Optional<A>
。因为匹配元素可能存在也可能不存在,在这种情况下 return 一个可选对象是一个很好的做法,而不是 returning null
以防找不到结果。它提供了更大的灵活性,而这正是设计可选选项的原因。
public Optional<A> getMatchingItem(List<A> listA, List<B> listB) {
Map<ValueHolder, A> aByValue = listA.stream()
.collect(Collectors.toMap(a -> new ValueHolder(a.getVal1(), a.getVal2()),
Function.identity()));
Map<ValueHolder, B> bByValue = listB.stream()
.collect(Collectors.toMap(b -> new ValueHolder(b.getVal1(), b.getVal2()),
Function.identity()));
return aByValue.keySet().stream()
.filter(bByValue::containsKey)
.findFirst()
.map(aByValue::get);
}