根据另一个对象的集合对对象列表进行分组

问题描述 投票:0回答:1

我想根据另一个对象列表 (

Promotions
) 对对象列表 (
Conditions
) 进行分组。
条件.java

class Promotion {
    String promoId;
    String promoDesc;
    String promoCode;
    Criteria criteria;
    
    public Promotion(String promoId, String promoDesc, String promoCode, Criteria criteria) {
        super();
        this.promoId = promoId;
        this.promoDesc = promoDesc;
        this.promoCode = promoCode;
        this.criteria = criteria;
    }
}

Criteria.java

class Criteria {

    String name;
    List<Condition> conditions;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List<Condition> getConditions() {
        return conditions;
    }
    public void setConditions(List<Condition> condition) {
        this.conditions = condition;
    }
}

和Condition.java是

class Condition {

    String attribute;
    String operator;
    String value;
    
    public Condition(String attribute, String operator, String value) {
        super();
        this.attribute = attribute;
        this.operator = operator;
        this.value = value;
    }
}

这是 GroupingTest.java

public class GroupingTest {

public static void (String[] args) {
        
        Condition cond1 = new Condition("term", "equals", "24");
        Condition cond2 = new Condition("term", "not equals", "12");
        
        Condition cond3 = new Condition("handset", "equals", "ABC");
        Condition cond4 = new Condition("handset", "equals", "XYZ");
        
        // ABC handset with term 24
        Criteria c1 = new Criteria();
        c1.setName("ABCwith24");        
        c1.setConditions(Arrays.asList(cond1,cond3));
        
        // XYZ handset with term 12
        Criteria c2 = new Criteria();
        c2.setName("XYZwith12");        
        c2.setConditions(Arrays.asList(cond2,cond4));
        
        // ABC handset with term 24
        Criteria c3 = new Criteria();
        c3.setName("handset24");        
        c3.setConditions(Arrays.asList(cond1,cond3));
        
        // XYZ handset with term 12
        Criteria c4 = new Criteria();
        c4.setName("handset12");        
        c4.setConditions(Arrays.asList(cond2,cond4));
        
        // XYZ handset with term 12
        Criteria c5 = new Criteria();
        c5.setName("XYZ24");        
        c5.setConditions(Arrays.asList(cond1,cond4));
        
        
        // new Promotion( promoId,promoDesc, promoCode, criteria)
        Promotion promo1 = new Promotion("P1", "Promo1", "ABC24", c1);
        Promotion promo2 = new Promotion("P2", "Promo2", "XYZ12", c2);
        Promotion promo3 = new Promotion("P3", "Promo3", "AAA24", c3);      
        Promotion promo4 = new Promotion("P4", "Promo4", "BBB12", c4);
        Promotion promo5 = new Promotion("P5", "Promo5", "CCC12", c5);
        
        List<Promotion> promos = Arrays.asList(promo1,promo2,promo3,promo4,promo5);
        
    //TODO grouping
        
    }

预期的结果是:

 Grp1 with promo1, promo3 (since conditions are matching though the criteria is different objects (c1, c3).
 Grp2 with promo2, promo4 ( conditions  of c2, c4 are same)
 Grp3 with promo5

有没有办法我们可以使用 java8 中的 Collectors.groupingBy() 或任何解决方法来做到这一点? 请注意,所有对象都是第三方供应商;所以无法访问代码库。

java java-8 stream grouping collectors
1个回答
0
投票

这样做就可以了:

    Map<String, List<Promotion>> promotionsGroupedByConditions = promos.stream()
            .collect(Collectors.groupingBy(promo -> {
                // the order of conditions should not matter
                promo.criteria.conditions.sort(comparator);
                return promo.criteria.conditions.stream()
                        .map(condition -> condition.attribute + "/" + condition.operator + "/" + condition.value)
                        .collect(Collectors.joining(" & "));
            }));

大概标准的顺序应该被忽略所以你需要这个:

public final static Comparator<? super Condition> comparator = new Comparator<Condition>() {

    @Override
    public int compare(Condition o1, Condition o2) {
        int attributeCompare = o1.attribute.compareTo(o2.attribute);
        if (attributeCompare != 0)
            return attributeCompare;
        int operatorCompare = o1.operator.compareTo(o2.operator);
        if (operatorCompare != 0)
            return operatorCompare;
        int valueCompare = o1.value.compareTo(o2.value);
        return valueCompare;

    }
};

并以可读形式打印它:

promotionsGroupedByConditions.entrySet().stream().forEach(entry -> {
    System.out.print(entry.getKey() + ": ");
    entry.getValue().forEach(v -> System.out.print(v.promoId + " "));
    System.out.println();
});

这是输出:

handset/equals/XYZ & term/not equals/12: P2 P4 
handset/equals/ABC & term/equals/24: P1 P3 
handset/equals/XYZ & term/equals/24: P5 
© www.soinside.com 2019 - 2024. All rights reserved.