代码之家  ›  专栏  ›  技术社区  ›  sree

Java泛化方法验证对象参数中的空值

  •  3
  • sree  · 技术社区  · 7 年前

    我试图实现一个逻辑,其中我有一个POJO类,它有7个属性。

    下面是实现

    Map<String,List<PriceClass>> map = new HashMap();
    for (PriceClass price : prices) {
      if (price.getAttribute1() !=null) {
          if (map.get("attribute1") !=null) {
                 map.get("attribute1").add(price);
          } else {
               map.set("attibute1",Collections.singletonList(price))
          }
       } else if(price.getAttribute2()!=null) {
           if (map.get("attribute12") !=null) {
                 map.get("attribute2").add(price);
           } else {
               map.set("attibute2",Collections.singletonList(price))
           }
       } else if (price.getAttribute3() !=null) {
         .
         .
         .
       } else if (price.getAttribute7() !=null) {
           //update the map
       }
    }
    

    我的问题是,如果有任何泛化实现,我可以在这里尝试,而不是编写这些if循环。

    8 回复  |  直到 7 年前
        1
  •  1
  •   Nikolas Charalambidis    7 年前

    一个可能的最优解类似于 one 我今天早些时候建议过。

    使用 Map<String, Optional<?>> 储存 Optional 具有未来输出映射键的键的选中属性的值。

    Map<String, Optional<?>> options = new HashMap<>();
    options.put("attribute1", Optional.ofNullable(price.getAttribute1()));
    // ...
    options.put("attribute3", Optional.ofNullable(price.getAttribute2()));
    // ...
    

    使用索引的迭代可以执行映射的更新。

    Map<String,List<Price>> map = new HashMap();
    for (int i=1; i<7; i++) {                                      // attributes 1..7
        String attribute = "attribute" + i;                        // attribute1...attribute7
        options.get(attribute).ifPresent(any ->                    // for non-nulls
                   map.put(                                        // put to the map
                       attribute,                                  // attribute as key remains
                       Optional.ofNullable(map.get(attribute))     // gets the existing list
                               .orElse(new ArrayList<>())          // or creates empty
                               .add(price)));                      // adds the current Price
    }
    

    Map::set

    map.set("attibute1",Collections.singletonList(price))
    

    你不是有意放一个 List<Price>

    map.put("attibute1", Collections.singletonList(price))
    

    出于这个原因,你可以使用我在上面发布的方式。

        2
  •  4
  •   Holger    7 年前

    你可以用

    Map<String,List<PriceClass>> map = new HashMap<>();
    for(PriceClass price: prices) {
        HashMap<String,Object> options = new HashMap<>();
        options.put("attibute1", price.getAttribute1());
        options.put("attibute2", price.getAttribute2());
        options.put("attibute3", price.getAttribute3());
        options.put("attibute4", price.getAttribute4());
        options.put("attibute5", price.getAttribute5());
        options.put("attibute6", price.getAttribute6());
        options.put("attibute7", price.getAttribute7());
        options.values().removeIf(Objects::isNull);
        options.keySet().forEach(attr -> map.computeIfAbsent(attr, x -> new ArrayList<>())
                                            .add(price));
    }
    

    准备一次不可修改的地图

    static final Map<String, Function<PriceClass,Object>> ATTR;
    static {
      Map<String, Function<PriceClass,Object>> a = new HashMap<>();
      a.put("attibute1", PriceClass::getAttribute1);
      a.put("attibute2", PriceClass::getAttribute2);
      a.put("attibute3", PriceClass::getAttribute3);
      a.put("attibute4", PriceClass::getAttribute4);
      a.put("attibute5", PriceClass::getAttribute5);
      a.put("attibute6", PriceClass::getAttribute6);
      a.put("attibute7", PriceClass::getAttribute7);
      ATTR = Collections.unmodifiableMap(a);
    }
    

    使用任何一种

    Map<String,List<PriceClass>> map = new HashMap<>();
    for(PriceClass price: prices) {
        HashMap<String,Object> options = new HashMap<>();
        ATTR.forEach((attr,func) -> options.put(attr, func.apply(price)));
        options.values().removeIf(Objects::isNull);
        options.keySet().forEach(attr -> map.computeIfAbsent(attr, x -> new ArrayList<>())
                                            .add(price));
    }
    

    Map<String,List<PriceClass>> map = prices.stream()
        .flatMap(price -> ATTR.entrySet().stream()
            .filter(e -> e.getValue().apply(price) != null)
            .map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), price)))
        .collect(Collectors.groupingBy(Map.Entry::getKey,
                    Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
    
        3
  •  1
  •   Oleg Cherednik    7 年前

    使用例如。 Enum 要定义7个不同的对象,每个对象负责具体的属性:

    // this is client code, looks pretty easy
    Map<String, List<PriceClass>> map = new HashMap<>();
    
    for (PriceClass price : prices)
        PriceAttribute.add(map, price);
    
    
    // all logic is hidden within special Enum    
    enum PriceAttribute {
        ATTRIBUTE1("attribute1", PriceClass::getAttribute1),
        ATTRIBUTE2("attribute2", PriceClass::getAttribute2),
        ATTRIBUTE3("attribute3", PriceClass::getAttribute3),
        ATTRIBUTE4("attribute4", PriceClass::getAttribute4),
        ATTRIBUTE5("attribute5", PriceClass::getAttribute5),
        ATTRIBUTE6("attribute6", PriceClass::getAttribute6),
        ATTRIBUTE7("attribute7", PriceClass::getAttribute7);
    
        private final String key;
        private final Function<PriceClass, ?> get;
    
        PriceAttribute(String key, Function<PriceClass, ?> get) {
            this.key = key;
            this.get = get;
        }
    
        public static void add(Map<String, List<PriceClass>> map, PriceClass price) {
            for (PriceAttribute attribute : values()) {
                if (attribute.get.apply(price) != null) {
                    map.computeIfAbsent(attribute.key, key -> new ArrayList<>()).add(price);    
                    break;
                }
            }
        }
    } 
    
        4
  •  0
  •   Goblin    7 年前

           if(map.get("attribute1") !=null)
             {
                 map.get("attribute1").add(price);
              }
            else
             {
               map.set("attibute1",Collections.singletonList(price))
              }
    

    它可以被重构成一个方法,并从父方法调用,这可以使它看起来更清晰一些。

    此外,您还可以尝试

    prices.removeAll(Collections.singleton(null))然后运行循环,以避免出现一个“If”条件。

        5
  •  0
  •   Pramod    7 年前

    以下代码段可以作为方法添加。

    if(map.get("attribute1") !=null) {
      map.get("attribute1").add(price);
    } else {
      map.set("attibute1",Collections.singletonList(price))
    }
    

    private static void addPrice(String attributeName, Price price){
        if(map.get(attributeName) !=null) {
          map.get(attributeName).add(price);
        } else {
          map.set(attributeName,Collections.singletonList(price))
        }
    }
    

    另外,映射应该是静态的,以便在这种情况下使用。

        6
  •  0
  •   rechandler    7 年前

    你打电话来 get

    if(map.get("attribute1") !=null) {
      map.get("attribute1").add(price);
    } else {
      map.set("attibute1",Collections.singletonList(price))
    }
    

    使用这个:

    final List<PriceClass> attribute1 = map.get("attribute1");
    if (attribute1 != null) {
        attribute1.add(price);
    } else {
        map.set("attibute1", Collections.singletonList(price))
    }
    

    Collections.singletonList 它创建了不可变列表,因此如果您尝试向其中添加某些内容(并执行该操作),则会出现异常。你应该用

    new ArrayList<PriceClass>(Arrays.asList(price))

    Stream.of(price).collect(toList())

        7
  •  0
  •   Toomtarm Kung    7 年前

    如果这是真正的代码,那么创建一个属性数组

    Attribute[] attributesOf(Price price){
        Attribute[] a = new Attribute[7];
        a[0] = price.getAttribute1();
        a[1] = price.getAttribute2();
        ...
        a[6] = price.getAttribute7();
    }
    

    如果有更多属性,只需修改此方法。然后你的代码可以重构成

    for(PriceClass price : prices){
        Attribute[] attributes = attributesOf(price);
        for(int i=0;i<attributes.length;i++){
        String key = "attribute" + (i+1);
            if(attributes[i] != null){
                map.get(key).add(price);
            }
            else{
                map.set(key, Collections.singletonList(price));
            }
        }
    }
    

    但是如果代码不同,比如price.getGrossAmount()、price.getNetAmount()、price.getTax(),则必须找到定义数组类型的通用约定。

    尽管如此,您必须了解良好的数据结构将使代码简单且性能良好。也许您不需要在price类中定义属性。也许您不需要price类,但可以使用BigDecimal作为价格值。

    我不太了解你的背景,我不知道你在做什么。我认为如果你展示真实的代码和它的上下文,你可能会从别人那里得到更好的答案。

        8
  •  0
  •   Pankaj Singhal    7 年前

    根据你的问题,好像 attibute1 出现在 PriceClass 阁楼1 钥匙。这意味着如果 prices 列表有 阁楼1 阁楼1 钥匙。

    public static void main(String[] args){
        Map<String,List<PriceClass>> map = new HashMap<>();
        List<PriceClass> prices =new ArrayList<>();
        prices.add(new PriceClass(1,2,3,4,5,6,7));
        prices.add(new PriceClass(null,12,13,14,15,16,17));
        map = prices.stream()
                .map(priceClass -> Arrays
                        .stream(PriceClass.class.getDeclaredFields())
                        .map(field -> getFieldValue(field, priceClass))
                        .filter(Objects::nonNull)
                        .findFirst()
                        .orElse(null)
                )
                .filter(Objects::nonNull)
                .collect(Collectors.groupingBy(AbstractMap.SimpleEntry::getKey,
                        Collectors.mapping(AbstractMap.SimpleEntry::getValue,
                                Collectors.toList())));
    
        System.out.println(map);
    }
    
    private static AbstractMap.SimpleEntry<String,PriceClass> getFieldValue(Field field, PriceClass priceClass){
        Optional<Integer> value = Optional.empty();
        try {
            value = Optional.ofNullable((Integer)field.get(priceClass));
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    
        if (value.isPresent()) {
            return new AbstractMap.SimpleEntry<>(field.getName(), priceClass);
        }
        return null;
    }
    

    输出:

    {attribute1=[PriceClass{attribute1=1, attribute2=2, attribute3=3, attribute4=4, attribute5=5, attribute6=6, attribute7=7}], 
    
     attribute2=[PriceClass{attribute1=null, attribute2=12, attribute3=13, attribute4=14, attribute5=15, attribute6=16, attribute7=17}]}
    
    推荐文章