Home > other >  Find value and set value from two list
Find value and set value from two list

Time:01-14

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)));
  • Related