java - Java:按属性值过滤2个不同对象的集合
问题描述
给定 2 个包含 2 种不同对象的列表(就像您从 API 获取一个集合以创建客户端或更新(如果存在)):
public static void main(String[] args) {
List<ClientA> clientsA = new ArrayList<>();
List<ClientB> clientsB = new ArrayList<>();
for (int i = 1; i <=5; i++) {
clientsA.add(new ClientA("JohnA-" + i, "DoeA-" + i, "A-" + i));
clientsB.add(new ClientB("JohnB-" + i, "DoeB-" + i, "B-" + i));
}
}
@Getter
@Setter
@AllArgsConstructor
static class ClientA {
private String firstName;
private String lastName;
private String ssNumber;
}
@Getter
@Setter
@AllArgsConstructor
static class ClientB {
private String firstName;
private String lastName;
private String security;
}
目的是建立一个新的ClientA
对象列表:
- 如果列表中存在
clientsA
与列表中客户端ssNumber
的值相同的条目,则更新找到的条目和属性;security
ClientB
firstName
lastName
- 否则,从列表中创建一个
ClientA
具有相同属性/值的新对象clientsB
,分配firstName
->firstName
,lastName
->lastName
,securityNumber
->ssNumber
。
我打算使用contains
orretainAll
方法,但它需要覆盖上述类,equals
而hashCode
我不能这样做。
我希望有这样的东西:
public void process() {
List<ClientA> clientsA = new ArrayList<>();
List<ClientB> clientsB = new ArrayList<>();
for (int i = 1; i <=5; i++) {
clientsA.add(new ClientA("John-" + i, "Doe-" + i, "A-" + i));
clientsB.add(new ClientB("JohnB-" + i, "DoeB-" + i, "B-" + i));
}
clientsA.add(new ClientA("Samantha", "Smith", "123456789"));
clientsB.add(new ClientB("Michael", "Smith", "123456789"));
findExistingEClientsA(clientsA, clientsB);
findNewClientsB(clientsA, clientsB);
}
private void findNewClientsB(List<ClientA> clientsA, List<ClientB> clientsB) {
Set resultSet = new HashSet();
for (ClientA clientA : clientsA) {
List<ClientB> collect = clientsB.stream().filter(c -> !c.getSecurity().equals(clientA.getSsNumber())).collect(Collectors.toList());
resultSet.addAll(collect);
}
System.out.println("+++++++ New clients B +++++++");
System.out.println(resultSet);
}
private void findExistingEClientsA(List<ClientA> clientsA, List<ClientB> clientsB) {
Set resultSet = new HashSet();
for (ClientA clientA : clientsA) {
List<ClientB> collect = clientsB.stream().filter(c -> c.getSecurity().equals(clientA.getSsNumber())).collect(Collectors.toList());
resultSet.addAll(collect);
}
System.out.println("++++++ existing clients B +++++++ ");
System.out.println(resultSet);
}
什么返回以下结果:
++++++ existing clients B +++++++
[ClientB{firstName='Michael', lastName='Smith', security='123456789'}]
+++++++ New clients B +++++++
[ClientB{firstName='JohnB-4', lastName='DoeB-4', security='B-4'}, ClientB{firstName='JohnB-2', lastName='DoeB-2', security='B-2'}, ClientB{firstName='JohnB-5', lastName='DoeB-5', security='B-5'}, ClientB{firstName='JohnB-3', lastName='DoeB-3', security='B-3'}, ClientB{firstName='JohnB-1', lastName='DoeB-1', security='B-1'}, ClientB{firstName='Michael', lastName='Smith', security='123456789'}]
这是一个好的解决方案还是有更好的解决方案?
但仍然没有成功。
解决方案
似乎对于这两种情况,都ClientA
应该从实例创建一个ClientB
实例并将其收集到一个新列表中,因此,应该将以下构造函数添加到ClientA
:
static class ClientA {
public ClientA(ClientB b) {
this(b.getFirstName(), b.getLastName(), b.getSecurity());
}
}
所以转换将是一个简单的重新映射:
List<ClientA> newA = clientsB.stream().map(ClientA::new).collect(Collectors.toList());
如果“update”表示需要将变更提升到clientsA
list,可以先建一个ClientA
by的map:ssNumber
Map<String, ClientA> map = clientsA.stream()
.collect(Collectors.toMap(
ClientA::getSsNumber, clientA -> clientA,
(c1, c2) -> c1 // select first clientB if duplicate entries are detected
));
然后可以像这样创建一个新列表:
List<ClientA> newA = new ArrayList<>();
clientsB.forEach(b -> {
ClientA a = map.getOrDefault(b.getSecurity(), new ClientA(b));
a.setFirstName(b.getFirstName());
a.setLastName(b.getLastName());
newA.add(a);
});
或者应该实现一个辅助方法(可能添加到ClientA
)以从 复制值ClientB
:
public static ClientA copyToA(ClientA a, ClientB b) {
Objects.requireNonNull(a);
Objects.requireNonNull(b);
a.setFirstName(b.getFirstName());
a.setLastName(b.getLastName());
return a;
}
那么新的列表ClientA
可能会以更多的streamed
方式构建:
List<ClientA> newClientsA = clientsB.stream()
.map(b -> map.containsKey(b.getSecurity())
? copyToA(map.get(b.getSecurity()), b)
: new ClientA(b)
)
.collect(Collectors.toList());
推荐阅读
- python - 在 Visual Studio 中创建 python 虚拟环境失败:返回非零退出状态 1
- c++ - 日期验证。即使我的日期实际上是有效的,也会继续循环
- python - Python - 将 300 个变量插入 SQLite
- python - Python 通过 selenium 将图像上传到站点
- javascript - 传单R,如何使与儿童统计相关的聚集图标出现?
- css - 右下角带有图标和文字的圆形功能区
- c# - 如何知道由多个对象实现的协同程序何时结束?
- java - Java Spring 设计:多合一组件?
- c++ - 我不懂 C++ 中的 ++ 运算符
- actionscript-3 - Flash AS3 - 将多个对象拖放到多个目标