我今天正在學習 lambda 運算式,到目前為止,我還沒有發現它們的獨特用途。所以我在問自己,它們是否不僅僅是取自函式式語言的一個方便的小工具。
什么是 Lambda 運算式?
據我所知,它們可用于實體化匿名類、傳遞簡單方法和過濾集合中的元素。例如:
List<Integer> list = List.of(1, 2, 3, 4, 5);
for (int i : list)
System.out.println(i);
...可以寫成:
List<Integer> list = List.of(1, 2, 3, 4, 5);
list.forEach((i) -> {
System.out.println(i);
});
但是你為什么要這樣做呢?每次你寫下一個 lambda 運算式時,你可以只把原始運算式放在那里!
public class Test {
@FunctionalInterface
interface BoolOperation {
boolean execute(boolean param1, boolean param2);
}
static void test(BoolOperation op, boolean param1, boolean param2) {
System.out.println(op.execute(param1, param2));
}
public static void main(String[] args) {
test((x, y) -> x && y, true, false);
test((x, y) -> x || y, false, true);
test((x, y) -> x == y, true, true);
}
}
...與以下相同:
public class Test {
public static void main(String[] args) {
System.out.println(true && false);
System.out.println(false || true);
System.out.println(true == true);
}
}
和
public class Test {
public static void main(String[] args) {
Runnable r = () -> {
System.out.println("Running.");
};
}
}
...并不比以下內容短/可讀得多:
public class Test {
public static void main(String[] args) {
Runnable r = new ThreadThingy();
}
}
class ThreadThingy implements Runnable {
public void run() {
System.out.println("Running.");
}
}
我已經閱讀了Oracle-Docs,但它們非常具體,并沒有突出一般用途。
uj5u.com熱心網友回復:
當然,您可以更輕松地直接撰寫帶有布爾運算式的示例。但是如果你想為不同的布爾運算式創建真值表怎么辦?
public class Test {
@FunctionalInterface
interface BoolOperation {
boolean execute(boolean param1, boolean param2);
}
static void line(String s, BoolOperation op, boolean b1, boolean b2) {
System.out.printf("%b %s %b = %b%n", b1, s, b2, op.execute(b1, b2));
}
static void table(String s, BoolOperation op) {
System.out.println("Truth table for " s);
line(s, op, false, false);
line(s, op, false, true);
line(s, op, true, false);
line(s, op, true, true);
System.out.println();
}
public static void main(String[] args) {
table("AND", (x, y) -> x && y);
table("OR", (x, y) -> x || y);
table("XNOR", (x, y) -> x == y);
table("XOR", (x, y) -> x != y);
table("implies", (x, y) -> !x || y);
}
}
您仍然可以使用匿名類進行各種操作,但這需要更多的“樣板”——需要撰寫的代碼只是為了滿足編譯器而不添加任何值。
例如,您可以table像這樣撰寫第一個呼叫:
table("AND", new BoolOperation() {
@Override
public boolean execute(boolean param1, boolean param2) {
return param1 && param2;
}
});
但你不能告訴我這比
table("AND", (x, y) -> x && y);
對于更多的“真實世界”的例子,我的一個專案包含一個類ObjectCsvWriter,需要一個PrintWriter和串列Column定義的物件串列匯出為CSV檔案。
列定義包含列名和 aFunction<T, X>用于從該行的物件中提取該列的值,X具體取決于列型別 - 對于StringColumn預期函式是 a Function<T, String>,對于DoubleColumn預期函式是 a Function<T, Double>。
匯出的代碼看起來像
private void exportXxx(List<ExportableXxx> data) {
List<Column<ExportableXxx>> columns = Arrays.asList(
new StringColumn<>("Xxx Id", ExportableXxx::getId),
new StringColumn<>("Xxx Name", ExportableXxx::getName),
new DoubleColumn<>("Total YYYY", "%.2f", ExportableXxx::getTotal),
new DoubleColumn<>("Yyyy Type 1", "%.2f", e -> e.getYyyy(Types.Type1)),
new DoubleColumn<>("Yyyy Type 2", "%.2f", e -> e.getYyyy(Types.Type2)),
new DoubleColumn<>("Yyyy Type 3", "%.2f", e -> e.getYyyy(Types.Type3)),
new DoubleColumn<>("Yyyy Type 4", "%.2f", e -> e.getYyyy(Types.Type4)),
new DoubleColumn<>("Yyyy Other", "%.2f", ExportableXxx::getYyyOther)
);
try (ObjectCsvWriter<ExportableXxx> cw = new ObjectCsvWriter<>(
new PrintWriter(fileName, Charset.defaultCharset()), columns)) {
cw.printHeader();
for (ExportableXxx d: data) {
cw.printLine(d);
}
} catch (IOException e) {
logger.warn("Cannot write export file", e);
}
}
您能想象為列出的每一列創建一個匿名類需要付出多大的努力嗎?(此示例不僅使用 lambda 來提取值,因為有時使用方法參考甚至更容易)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/369648.html
