Фильтрующий список, свойство которого не включено в свойство другого списка - PullRequest
0 голосов
/ 14 февраля 2019
public class Bill {
    private Long code;

    public Bill(Long code) {
        this.code = code;
    }
    // setters and Getters
}

class Detail {
    private BillId billId;

    public Detail(BillId billId) {
        this.billId = billId;
    }
    // setters and Getters

}

class BillId {
    private Long number;
    private Long code;

    public BillId(Long number, Long code) {
        this.number = number;
        this.code = code;
    }
    // setters and Getters
}

Теперь у меня есть

List<Bill> listBill = new ArrayList<>();
listBill.add(new Bill(1L));
listBill.add(new Bill(2L));
listBill.add(new Bill(3L));
listBill.add(new Bill(4L));
listBill.add(new Bill(5L));
listBill.add(new Bill(6L));


List<Detail> listDetail = new ArrayList<>();
listDetail.add(new Detail(new BillId(1000L, 10L)));
listDetail.add(new Detail(new BillId(1000L, 2L)));
listDetail.add(new Detail(new BillId(2000L, 30L)));
listDetail.add(new Detail(new BillId(2000L, 4L)));
listDetail.add(new Detail(new BillId(3000L, 50L)));
listDetail.add(new Detail(new BillId(3000L, 6L)));

Теперь мне нужно new List забрать предметы из listBill, где какой-то предмет НЕ СОГЛАСЕН с каким-то предметом из listDetail

detail.getBillId ().getCode() not match with bill.getCode()

Ожидаемый список Извините за Новых!

newListBill.add(new Bill(1L)); 
newListBill.add(new Bill(3L));
newListBill.add(new Bill(5L));

Ответы [ 5 ]

0 голосов
/ 14 февраля 2019

Еще один вариант существующего ответа с использованием noneMatch, чтобы избежать явного отрицания:

List<Bill>  output = listBill.stream()
        .filter( b -> listDetail.stream()
              .noneMatch(d -> d.getBillId().getCode().equals(b.getCode()))) // change here
        .collect(toList());
0 голосов
/ 14 февраля 2019

Существует более оптимальное решение со сложностью O (nlogn).Сначала получите список кодов из деталей:

List<Long> codes = listDetail.stream()
            .map(detail -> detail.getBillId().getCode())
            .sorted()
            .collect(Collectors.toList());

А теперь сделайте фильтр с двоичным поиском (codes уже отсортировано):

List<Bill> collect = listBill.stream()
            .filter(bill -> Collections.binarySearch(codes, bill.getCode()) < 0)
            .collect(Collectors.toList());

System.out.println(collect);      // [Bill{code=1}, Bill{code=3}, Bill{code=5}]
0 голосов
/ 14 февраля 2019

Вы можете просто перебрать оба списка и сравнить переменную кода (насколько я понимаю, это единственный критерий, который вы хотите сравнить?):

    ArrayList<Bill> result = new ArrayList<>();
    for(Bill bill: listBill) {
       for(Detail detail : listDetail) {
          if(bill.getCode() == detail.getBillId().getCode() {
                result.add(bill);
        }
      }
}
0 голосов
/ 14 февраля 2019

Использование Stream, Java 8

    List<Bill> substractListBill = listBill.stream().filter(bill -> !listDetail.stream()
            .map(Detail::getBillId)
            .map(BillId::getCode)
            .anyMatch(code ->  Objects.equals(code, bill.getCode())))
            .collect(Collectors.toList());
    System.out.println(substractListBill);
0 голосов
/ 14 февраля 2019

Использование потокового API:

listBill.stream()
.filter( b -> !listDetail.stream()
     .anyMatch( d -> d.getBillId().getCode() == b.getCode() ) )
.collect( Collectors.toList() );
...