这个问题似乎有些争议(在撰写本文时+5/-3)。
正如您所提到的,这里的命令式解决方案很可能是最简单、最合适和可读的解决方案。
函数式或声明式风格并没有真正“失败”。它提出了关于确切目标、条件和上下文的问题,甚至可能是关于语言细节的哲学问题(比如为什么Pair
核心 Java 中没有标准类)。
您可以在此处应用功能解决方案。一个简单的技术问题是您是否真的要填写现有列表,或者是否可以创建新列表。在这两种情况下,您都可以使用该Collectors#groupingBy
方法。
在这两种情况下,分组标准是相同的:即,一个项目的特定组合的任何“表示isA
” isB
。对此有不同的可能解决方案。在下面的示例中,我使用 anEntry<Boolean, Boolean>
作为键。
(如果您有其他条件,例如isC
and isD
,那么您实际上也可以使用 a 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 + ")";
}
}
}