I have a list of
List<User> userList = ...
List<Long> UserIdWithBilling = .....
I search to set a field of User to true if the value in the list of UserIdWithBilling are found in the userList id field
for(Long userId : UserIdWithBilling){
Optional<User> optUserList = userList.stream()
.filter(ul->ul.getUserId().longValue()==userId)
.findFirst();
if(optUserList.isPresent()){
optUserList.get().setBilling(true);
}
}
that work but is there a way clean, faster
Maybe there is a way to do in via one line
CodePudding user response:
Convert UserIdWithBilling
to a set, then use contains
in the filter
.
Set<Long> ids = new HashSet<>(UserIdWithBilling);
userList.stream()
.filter(x -> ids.contains(x.getUserId()))
.forEach(x -> x.setBilling(true));
CodePudding user response:
Here is the executable test with the old and new solution (as a one-liner)
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
public class UserList {
List<User> userList = new ArrayList<User>();
List<Long> userIdsWithBilling = new ArrayList<>();
@BeforeAll
public void setup() {
for (long id=1l; id<=10l; id ) userList.add(new User(id, false));
for (long id=1l; id<=5l; id ) userIdsWithBilling.add(id);
}
@Test
public void oldSolution() {
for (Long userId : userIdsWithBilling) {
Optional<User> optUserList = userList.stream()
.filter(ul -> ul.getId().longValue() == userId)
.findFirst();
if (optUserList.isPresent()) {
optUserList.get().setBilling(true);
}
}
for (int i=0; i<5; i ) assertTrue(userList.get(i).getBilling());
for (int i=5; i<10; i ) assertFalse(userList.get(i).getBilling());
}
@Test
public void newSolution() {
userList.stream().filter(user -> userIdsWithBilling.contains(user.getId()))
.forEach(user -> user.setBilling(true));
for (int i=0; i<5; i ) assertTrue(userList.get(i).getBilling());
for (int i=5; i<10; i ) assertFalse(userList.get(i).getBilling());
}
private static class User {
private Long id;
private Boolean billing = false;
public User(long id, boolean billing) {
this.id = id;
this.billing = billing;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public void setBilling(Boolean billing){
this.billing = billing;
}
public Boolean getBilling(){
return billing;
}
}
}
For large lists you can use parallel streams but please read the docs on that.
CodePudding user response:
On one line, but keep in mind it changes the billing to true on the original userList
. You have to rewrite if you want a new list like in your question.
UserIdWithBilling.forEach(
billedUser -> userList.stream().filter(u -> u.getUserId() == billedUser).toList()
.forEach(u -> u.setBilling(true)));