Есть ли лучший способ обработки нескольких пустых проверок в Java? - PullRequest
6 голосов
/ 12 мая 2019

У меня есть код ниже

Set<Product> getallProducts(){

    Product p = getProduct(brand, price);
    Product p1 = getProduct(brand, price, location);
    Product p2 = getProduct(brand, price, qty);

   Set<SuperProducts> superProducts = new HashSet<>;


   if(p!=null){
      SuperProduct sp  = getSuperProduct(p)
      superProducts.add(sp)
   }

   if(p1!=null){
      SuperProduct sp1  = getSuperProduct(p1)
      superProducts.add(sp)

   }

   if(p2!=null){
      SuperProduct sp2  = getSuperProduct(p2)
      superProducts.add(sp2)

    }
}

Есть ли четкий способ обработки p! = Null, p2! = Null, p1! = Null.Я могу добавить p, p1, p2 в список и выполнить итерацию по нему, как показано ниже , но я искал более дешевый способ, чем добавление продуктов в список и последующая итерация по ним.Кроме того, я хотел бы, чтобы проверка на нулевое значение каждый раз обходилась дороже, чем добавление в список и повторение по нему?

List<Product> products = new ArrayList<>():
products.add(p);
products.add(p1);
products.add(p2);

and 
for(Product p:products){
// and adding to superProducts
}

Ответы [ 4 ]

10 голосов
/ 12 мая 2019

Вы можете перейти на Stream.of и затем filter как:

return Stream.of(p1, p2, p3).filter(Objects::nonNull)
                            .map(this::getSuperProduct)
                            .collect(Collectors.toSet());
2 голосов
/ 12 мая 2019

Учитывая, что одна и та же кодовая последовательность повторяется 3 раза, я бы написал служебный метод:

 private void addSuper(Product p, Set<SuperProduct> s) {
   if (p != null)
      s.add(getSuperProduct(p));
 }

, а затем

Set<SuperProduct> superProducts = new HashSet<>();
addSuper(getProduct(brand, price), superProducts);
addSuper(getProduct(brand, price, location), superProducts);
addSuper(getProduct(brand, price, qty), superProducts);

Моя главная задача при проведении этого рефакторинга - это не «тест на ненулевое значение», а повторяющийся характер оригинала.

2 голосов
/ 12 мая 2019

Вот способ сделать это, используя Optional, не намного дольше, чем другие ответы, так как каждый объект Product должен быть создан в любом случае.

Set<Product> getallProducts() {
    Set<SuperProducts> superProducts = new HashSet<>;

    Optional.ofNullable(getProduct(brand, price))
        .ifPresent(prod -> superProducts.add(new SuperProduct(prod)));
    Optional.ofNullable(getProduct(brand, price, location))
        .ifPresent(prod -> superProducts.add(new SuperProduct(prod)));
    Optional.ofNullable(getProduct(brand, price, qty))
        .ifPresent(prod -> superProducts.add(new SuperProduct(prod)));

    return superProducts;
}
1 голос
/ 12 мая 2019

Если вы ищете наиболее эффективный способ сделать это, придерживайтесь того способа, которым вы сейчас занимаетесь. Ваше решение многословно, но, вероятно, настолько эффективно, насколько это возможно. И нет никаких сомнений в том, что ваш код легче понять, чем другие альтернативы.

Если вы ищете решения, которые используют меньше строк кода, вы можете реализовать это с помощью потоков и фильтров или путем создания массива или списка ссылок Product и итерации. Однако все эти решения влекут за собой создание временных структур данных и существенно менее эффективны.


Обратите внимание, что если вызов getSuperProduct(p) встроен JIT-компилятором, то он может оптимизировать тест импликации для null, который происходит в вызове.


Кроме того, я хотел бы, чтобы проверка на нулевое значение каждый раз обходилась дороже, чем добавление в список и итерация по нему?

Я думаю, что вы найдете обратное дело. Вам нужно будет выполнить нулевые проверки в любом случае (или нет ... см. Выше). Когда вы пытаетесь использовать список, массив или поток, у вас возникают накладные расходы на создание структуры данных (один или несколько новых объектов кучи для создания и инициализации), и у вас возникают накладные расходы на тестирование, когда вы дойдете до конца списка /array/stream.


И последнее, на что нужно обратить внимание: эффективность кода, подобного этому, часто не имеет значения. Мы, вероятно, говорим о разнице менее чем в 100 инструкциях; то есть разница менее 1 мкс. Это, вероятно, тривиально по сравнению с остальной частью того, что делает приложение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...