Вопрос несколько спорный, как кажется (+5/-3 на момент написания этого).
Как вы упомянули, императивное решение здесь, скорее всего, самое простое, подходящее и читаемое.
Функциональный или декларативный стиль на самом деле не «проваливается». Это скорее поднимает вопросы о точных целях, условиях и контексте и, возможно, даже философские вопросы о деталях языка (например, почему в ядре Java нет стандартного класса Pair
).
Здесь вы можете применить функциональное решение. Тогда возникает простой технический вопрос: действительно ли вы хотите заполнять существующие списки или можно создавать новые списки. В обоих случаях вы можете использовать Collectors#groupingBy
.
Критерий группировки один и тот же в обоих случаях: а именно, любое «представление» конкретной комбинации isA
и isB
одного элемента. Для этого есть разные возможные решения. В приведенных ниже примерах я использовал Entry<Boolean, Boolean>
в качестве ключа.
(Если бы у вас были дополнительные условия, такие как isC
и isD
, то вы могли бы также использовать List<Boolean>
).
В примере показано, как вы можете либо добавить элемент в существующие списки (как в вашем вопросе), либо создать новые списки (что немного проще и чище).
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
public class FunctionalIfElse
{
public static void main(String[] args)
{
List<Item> items = new ArrayList<Item>();
items.add(new Item(false, false));
items.add(new Item(false, true));
items.add(new Item(true, false));
items.add(new Item(true, true));
fillExistingLists(items);
createNewLists(items);
}
private static void fillExistingLists(List<Item> items)
{
System.out.println("Filling existing lists:");
List<Item> itemIsBoth = new ArrayList<Item>();
List<Item> aItems = new ArrayList<Item>();
List<Item> bItems = new ArrayList<Item>();
Map<Entry<Boolean, Boolean>, List<Item>> map =
new LinkedHashMap<Entry<Boolean, Boolean>, List<Item>>();
map.put(entryWith(true, true), itemIsBoth);
map.put(entryWith(true, false), aItems);
map.put(entryWith(false, true), bItems);
items.stream().collect(Collectors.groupingBy(
item -> entryWith(item.isA(), item.isB()),
() -> map, Collectors.toList()));
System.out.println("Both");
itemIsBoth.forEach(System.out::println);
System.out.println("A");
aItems.forEach(System.out::println);
System.out.println("B");
bItems.forEach(System.out::println);
}
private static void createNewLists(List<Item> items)
{
System.out.println("Creating new lists:");
Map<Entry<Boolean, Boolean>, List<Item>> map =
items.stream().collect(Collectors.groupingBy(
item -> entryWith(item.isA(), item.isB()),
LinkedHashMap::new, Collectors.toList()));
List<Item> itemIsBoth = map.get(entryWith(true, true));
List<Item> aItems = map.get(entryWith(true, false));
List<Item> bItems = map.get(entryWith(false, true));
System.out.println("Both");
itemIsBoth.forEach(System.out::println);
System.out.println("A");
aItems.forEach(System.out::println);
System.out.println("B");
bItems.forEach(System.out::println);
}
private static <K, V> Entry<K, V> entryWith(K k, V v)
{
return new SimpleEntry<K, V>(k, v);
}
static class Item
{
private boolean a;
private boolean b;
public Item(boolean a, boolean b)
{
this.a = a;
this.b = b;
}
public boolean isA()
{
return a;
}
public boolean isB()
{
return b;
}
@Override
public String toString()
{
return "(" + a + ", " + b + ")";
}
}
}
person
Marco13
schedule
18.07.2019
filter
, но неelse
. В какой-то момент вам придется иметь эту разветвленную структуру. Если я ошибаюсь, я с удовольствием научусь это делать :) - person Antoniossss   schedule 18.07.2019if
/else
обязательны в Java, заключается в том, что они разработаны как операторы. Если бы это было выражение, оно заставляло бы вас всегда указывать регистрelse
по умолчанию, чтобы оно в любом случае давало значение. Долгая история, короткая история: условное ветвление является декларативным, и обычно нет разумных причин для его преобразования. - person Iven Marquardt   schedule 18.07.2019Item::getType
, и использовать его вCollectors::groupingBy
- person Adrian   schedule 18.07.2019(item.isA()? item.isB()? itemIsBoth: aItems: item.isB()? bItems: new ArrayList<>()).add(item);
- person Holger   schedule 18.07.2019if
/then
/else
, охранники иcase
структуры управления, которые являются выражениями. и может быть вложенным. - person Iven Marquardt   schedule 18.07.2019switch
, что похоже на выражениеcase
в Haskell. Он уже включен в качестве экспериментальной функции в последние версии JDK. - person Holger   schedule 19.07.2019