Given 2 Lists containing 2 kinds of different objects (as if you are getting a collection from an API to create a client or update if it exists):
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;
}
The purpose is to build a new list of ClientA
objects:
clientsA
list with the same ssNumber
value equal to the security
value of the clients in ClientB
list, update the found entry firstName
and lastName
attributes;ClientA
object with the same attributes/values from the clientsB
list, assigning firstName
-> firstName
, lastName
-> lastName
, securityNumber
-> ssNumber
. I was going to use contains
or retainAll
methods, but it requires overriding equals
and hashCode
of the above classes what I can't do.
I expecting to have something like this:
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);
}
What returns the below result:
++++++ 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'}]
Is it a good solution or there is a better one?
But still no success.
It seems that for both cases an instance of ClientA
should be created from ClientB
instances and collected into a new list, thus, the following constructor should be added to ClientA
:
static class ClientA {
public ClientA(ClientB b) {
this(b.getFirstName(), b.getLastName(), b.getSecurity());
}
}
So the conversion would be a simple remapping:
List<ClientA> newA = clientsB.stream().map(ClientA::new).collect(Collectors.toList());
If the "update" means that the change needs to be promoted to clientsA
list, a map of ClientA
by ssNumber
can be built first:
Map<String, ClientA> map = clientsA.stream()
.collect(Collectors.toMap(
ClientA::getSsNumber, clientA -> clientA,
(c1, c2) -> c1 // select first clientB if duplicate entries are detected
));
Then a new list can be created like this:
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);
});
Or a helper method should be implemented (possibly added to ClientA
) to copy the values from 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;
}
Then the new list of ClientA
may be built in a more streamed
way:
List<ClientA> newClientsA = clientsB.stream()
.map(b -> map.containsKey(b.getSecurity())
? copyToA(map.get(b.getSecurity()), b)
: new ClientA(b)
)
.collect(Collectors.toList());
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.