亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

從 Java 8 中基于多個屬性的對象列表中刪除重復項

從 Java 8 中基于多個屬性的對象列表中刪除重復項

郎朗坤 2023-02-23 11:18:14
我想比較 getCode & getMode 并找到重復的記錄。然后還有一個產品屬性 getVode,它在兩條記錄中始終具有不同的值(真或假)。P1   getCode  getMode  getVode1    001      123      trueP2   getCode  getMode  getVode2    001      123      false我在下面嘗試過,但它只找到重復項:List<ProductModel> uniqueProducts = productsList.stream()    .collect(Collectors.collectingAndThen(        toCollection(() -> new TreeSet<>(            Comparator.comparing(ProductModel::getCode)                .thenComparing(ProductModel::getMode)        )),        ArrayList::new));因此,當我找到重復記錄時,我想檢查 getVode 值為 false 并將其從列表中刪除。任何幫助,將不勝感激?
查看完整描述

4 回答

?
MMMHUHU

TA貢獻1834條經驗 獲得超8個贊

據我了解,只有當元素重復并且它們的getVode方法返回時,您才想刪除元素false。

我們可以從字面上做到這一點。首先,我們必須確定哪些元素是重復的:

Map<Object, Boolean> isDuplicate = productsList.stream()
    .collect(Collectors.toMap(pm -> Arrays.asList(pm.getCode(), pm.getMode()),
                              pm -> false, (a, b) -> true));

然后,刪除那些滿足條件的:

productsList.removeIf(pm -> !pm.getVode()
                         && isDuplicate.get(Arrays.asList(pm.getCode(), pm.getMode())));

或者,不修改舊列表:

List<ProductModel> uniqueProducts = new ArrayList<>(productsList);
uniqueProducts.removeIf(pm -> !pm.getVode()
                           && isDuplicate.get(Arrays.asList(pm.getCode(), pm.getMode())));

這也可以通過 Stream 操作來完成:

List<ProductModel> uniqueProducts = productsList.stream()
    .filter(pm -> pm.getVode()
              || !isDuplicate.get(Arrays.asList(pm.getCode(), pm.getMode())))
    .collect(Collectors.toList());


查看完整回答
反對 回復 2023-02-23
?
qq_遁去的一_1

TA貢獻1725條經驗 獲得超8個贊

在這里,無論值是什么,您都刪除了重復項getVode(),因為在傳遞Comparator給TreeSet.

你的方法不容易。您可以根據可以用類表示的元素和值對元素進行分組來

創建。 然后對于 Map 進程的每個條目:如果列表包含單個元素,則保留它,否則不要保留所有這些必須為false 的元素。 Map<ProductModelId, List<ProductModelId>>getCode()getMode()ProductModelId

getVode()


Map<ProductModelId, List<ProductModel>> map = 

productsList.stream()

            .collect(groupingBy(p -> new ProductModelId(p.getCode(), p.getMode());


List<ProductModel> listFiltered =

        map.values()

           .stream()

           .flatMap(l -> {

                        if (l.size() == 1) {

                          return Stream.of(l.get(0));

                        } else {

                          return l.stream().filter(ProductModel::getVode);

                        }

                    }

           )

           .collect(toList());

請注意,ProductModelId應該equals/hashCode通過考慮兩個字段的值來覆蓋它們以在地圖中正確地對它們進行分組:


public class ProductModelId {


    private String code;

    private String mode;


    public ProductModelId(String code, String mode) {

        this.code = code;

        this.mode = mode;

    }


    @Override

    public boolean equals(Object o) {

        if (this == o) return true;

        if (!(o instanceof ProductModelId)) return false;

        ProductModelId that = (ProductModelId) o;

        return Objects.equals(code, that.code) &&

                Objects.equals(mode, that.mode);

    }


    @Override

    public int hashCode() {

        return Objects.hash(code, mode);

    }

}


查看完整回答
反對 回復 2023-02-23
?
慕尼黑8549860

TA貢獻1818條經驗 獲得超11個贊

如果您vode可以用于true多個實例ProductModel(否則,如果您期望一個實例true- 這更簡單,我會讓這個練習給您)并且您想要保留所有實例,這可能就是您想要的:


    List<ProductModel> models = List.of(

        new ProductModel(1, 123, false),

        new ProductModel(1, 123, true)); // just an example


    Map<List<Integer>, List<ProductModel>> map = new HashMap<>();


    models.forEach(x -> {


        map.computeIfPresent(Arrays.asList(x.getMode(), x.getCode()),

                             (key, value) -> {

                                 value.add(x);

                                 value.removeIf(xx -> !xx.isVode());

                                 return value;

                             });

        map.computeIfAbsent(Arrays.asList(x.getMode(), x.getCode()),

                            key -> {

                                List<ProductModel> list = new ArrayList<>();

                                list.add(x);

                                return list;

                            });

    });


    map.values()

       .stream()

       .flatMap(List::stream)

       .forEachOrdered(x -> System.out.println(x.getCode() + "  " + x.getMode()));

哪里ProductModel是這樣的:


    static class ProductModel {


    private final int code;

    private final int mode;

    private final boolean vode;


    // some other fields, getters, setters


}

這不是那么容易實現的。您首先需要查找是否存在重復項,并且只有在找到重復項時才采取相應措施。map.computeIfAbsent注意放入地圖鍵(aKey由Code/Mode包裹在Arrays::asList- 它正確覆蓋hashCode/equals)。


當基于該 Key 找到重復項時,我們希望通過map.computeIfPresent. “表演”也不是微不足道的,考慮到它vode可以true跨越多個實例(是的,這是我的假設)。你不知道vode之前的鑰匙在這張地圖上放了什么——是嗎false?如果是這樣,它必須被刪除。但是電流false也是嗎?如果是這樣,它也必須被刪除。


查看完整回答
反對 回復 2023-02-23
?
慕少森

TA貢獻2019條經驗 獲得超9個贊

您可以按代碼和模式的組合進行分組。然后在 mergeFunction 中獲取帶有truevode 的元素:

 Collection<ProductModel> uniqueProducts  = products.stream()
        .collect(toMap(
                    p -> Arrays.asList(p.getCode(), p.getMode()),
                    Function.identity(),
                    (p1, p2) -> p1.getVode() ? p1 : p2))
        .values();

請參閱javaDoc 了解 toMap


查看完整回答
反對 回復 2023-02-23
  • 4 回答
  • 0 關注
  • 189 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號