5 回答

TA貢獻(xiàn)1834條經(jīng)驗(yàn) 獲得超8個(gè)贊
問題標(biāo)題相當(dāng)廣泛(轉(zhuǎn)換 if-else 階梯),但由于實(shí)際問題詢問的是特定場景,所以讓我提供一個(gè)示例,至少可以說明可以做什么。
因?yàn)樵搃f-else結(jié)構(gòu)基于應(yīng)用于項(xiàng)目的謂詞創(chuàng)建了三個(gè)不同的列表,所以我們可以將此行為更明確地表達(dá)為分組操作。要開箱即用,唯一需要做的額外工作是使用標(biāo)記對象折疊多個(gè)布爾謂詞。例如:
class Item {
enum Category {A, B, AB}
public Category getCategory() {
return /* ... */;
}
}
那么邏輯可以簡單的表達(dá)為:
Map<Item.Category, List<Item>> categorized =
items.stream().collect(Collectors.groupingBy(Item::getCategory));
其中每個(gè)列表都可以從給定類別的地圖中檢索。
如果無法更改 class Item,則可以通過移動 enum 聲明和分類方法使其超出類Item(該方法將成為靜態(tài)方法)來實(shí)現(xiàn)相同的效果。

TA貢獻(xiàn)1795條經(jīng)驗(yàn) 獲得超7個(gè)贊
另一種使用 Vavr 并只對項(xiàng)目列表進(jìn)行一次迭代的解決方案可以使用以下方法實(shí)現(xiàn)foldLeft:
list.foldLeft(
Tuple.of(List.empty(), List.empty(), List.empty()), //we declare 3 lists for results
(lists, item) -> Match(item).of(
//both predicates pass, add to first list
Case($(allOf(Item::isA, Item::isB)), lists.map1(l -> l.append(item))),
//is a, add to second list
Case($(Item::isA), lists.map2(l -> l.append(item))),
//is b, add to third list
Case($(Item::isB), lists.map3(l -> l.append(item)))
))
);
它將返回一個(gè)包含三個(gè)結(jié)果列表的元組。

TA貢獻(xiàn)1777條經(jīng)驗(yàn) 獲得超3個(gè)贊
既然你提到了 vavr 作為標(biāo)簽,我將提供一個(gè)使用 vavr 集合的解決方案。
import static io.vavr.Predicates.allOf;
import static io.vavr.Predicates.not;
...
final Array<Item> itemIsBoth = items.filter(allOf(Item::isA, Item::isB));
final Array<Item> aItems = items.filter(allOf(Item::isA, not(Item::isB)));
final Array<Item> bItems = items.filter(allOf(Item::isB, not(Item::isA)));
該解決方案的優(yōu)點(diǎn)是簡單易懂,一目了然,而且它的功能與 Java 一樣。缺點(diǎn)是它將遍歷原始集合三次而不是一次。這仍然是一個(gè)O(n),但乘數(shù)為 3。在非關(guān)鍵代碼路徑和小型集合中,為了代碼清晰度而犧牲幾個(gè) CPU 周期可能是值得的。
當(dāng)然,這也適用于所有其他 vavr 集合,因此您可以替換Array為List、Vector、Stream等。

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超5個(gè)贊
擺脫 the 的另一種方法if-else是將它們替換為Predicateand Consumer:
Map<Predicate<Item>, Consumer<Item>> actions =
Map.of(item.predicateA(), aItems::add, item.predicateB(), bItems::add);
actions.forEach((key, value) -> items.stream().filter(key).forEach(value));
因此,您需要增強(qiáng)Item這兩種方法predicateA()并使用您在和predicateB()中實(shí)現(xiàn)的邏輯isA()isB()
順便說一句,我仍然建議使用你的if-else邏輯。

TA貢獻(xiàn)1801條經(jīng)驗(yàn) 獲得超16個(gè)贊
當(dāng)然可以。功能方式是使用聲明方式。
在數(shù)學(xué)上你正在設(shè)置一個(gè)Equivalence relation,然后,你可以寫
Map<String, List<Item>> ys = xs
.stream()
.collect(groupingBy(x -> here your equivalence relation))
一個(gè)簡單的例子說明了這一點(diǎn)
public class Main {
static class Item {
private final boolean a;
private final boolean b;
Item(boolean a, boolean b) {
this.a = a;
this.b = b;
}
public boolean isB() {
return b;
}
public boolean isA() {
return a;
}
}
public static void main(String[] args) {
List<Item> xs = asList(new Item(true, true), new Item(true, true), new Item(false, true));
Map<String, List<Item>> ys = xs.stream().collect(groupingBy(x -> x.isA() + "," + x.isB()));
ys.entrySet().forEach(System.out::println);
}
}
帶輸出
true,true=[com.foo.Main$Item@64616ca2, com.foo.Main$Item@13fee20c]
false,true=[com.foo.Main$Item@4e04a765]
添加回答
舉報(bào)