0

これをきちんと行うラムダジの方法はありますか?タイトルが複雑に聞こえることは承知していますが、以下のコード フラグメントで明確にする必要があります。

private List<String[]> getContractLineItemsForDatatables(List<ContractLineItem> contractLineItems) {

    List<String[]> contractLineItemsForDatatables = Lists.newArrayList();

    for (ContractLineItem contractLineItem : contractLineItems) {

        contractLineItemsForDatatables.add( contractLineItem.getDataTablesRow());
    }

    return contractLineItemsForDatatables;
}

上記の for ループを回避するために Lambdaj でこれを行うきちんとした方法があるに違いありませんが、私はそれについて頭を悩ませることができません。ところで、contractLineItem.getDatatablesRow() は String[] を返します。

だから私がやりたいことは次のとおりです。

contractLineItems リストのすべての要素に対して getDataTablesRow() を実行し、それらを contactLineItemsForDatatables リストに追加します。

助言がありますか?

4

2 に答える 2

4

言葉遣いのほとんどは、Java コードではなく、変数名の選択に由来します。

private static List<String[]> extractDataTableRows(List<ContractLineItem> items) {
    List<String[]> ret = new ArrayList<>();
    for (ContractLineItem item : items) ret.add(item.getDataTablesRow());
    return ret;
}

例外がスローされた場合、次のようになります

Exception in thread "main" java.lang.RuntimeException
at Main$ContractLineItem.getDataTablesRow(Main.java:87)
at Main.extractDataTableRows(Main.java:50)
at Main.main(Main.java:27)

グアバのラムダの使用

private static List<String[]> extractDataTableRows(List<ContractLineItem> items) {
    return Lists.transform(items, new Function<ContractLineItem, String[]>() {
        @Override
        public String[] apply(ContractLineItem item) {
            return item.getDataTablesRow();
        }
    });
}

例外がスローされた場合、次のようになります

Exception in thread "main" java.lang.RuntimeException
at Main$ContractLineItem.getDataTablesRow(Main.java:76)
at Main$1.apply(Main.java:38)
at Main$1.apply(Main.java:35)
at com.google.common.collect.Lists$TransformingRandomAccessList.get(Lists.java:495)
at java.util.AbstractList$Itr.next(AbstractList.java:358)
at java.util.AbstractCollection.toString(AbstractCollection.java:459)
at java.lang.String.valueOf(String.java:2957)
at java.io.PrintStream.println(PrintStream.java:821)
at Main.main(Main.java:31)

注: List が使用されるまで、例外はトリガーされません。

このGuava の警告は、私には十分に明確です。

Java 7 の時点で、Java での関数型プログラミングは、無名クラスの厄介で冗長な使用によってのみ近似できます。これは Java 8 で変更される予定ですが、Guava は現在 Java 5 以降のユーザーを対象としています。

Guava の関数型プログラミング イディオムを過度に使用すると、コードが冗長になり、混乱を招き、判読不能で非効率的なコードになる可能性があります。これらは Guava の最も簡単に (そして最も一般的に) 悪用される部分であり、コードを「ワンライナー」にするためにばかげた長さになると、Guava チームは泣きます。

Java 8 を使用しています。

private static List<String[]> extractDataTableRows(List<ContractLineItem> items) {
    return items.stream()
            .<String[]>map(ContractLineItem::getDataTablesRow)
            .into(new ArrayList<>());
}

あなたが書くことができるユーティリティメソッドを追加する

public static <E, R> List<R> map(Collection<E> elements, Function<? super E, ? extends R> function) {
    return elements.stream().<R>map(function).into(new ArrayList<R>());
}

// hiding the guff, this is more readable IMHO.
private static List<String[]> extractDataTableRows(List<ContractLineItem> items) {
    return map(items, ContractLineItem::getDataTablesRow);
}

例外がスローされた場合、次のようになります

 Exception in thread "main" java.lang.RuntimeException
at Main$ContractLineItem.getDataTablesRow(Main.java:77)
at Main$$Lambda$1.apply(Unknown Source)
at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:87)
at java.util.Arrays$ArraySpliterator.forEach(Arrays.java:4551)
at java.util.stream.AbstractPipeline$PipelineHelperImpl.into(AbstractPipeline.java:197)
at java.util.stream.op.ForEachOp.evaluateSequential(ForEachOp.java:86)
at java.util.stream.op.ForEachOp.evaluateSequential(ForEachOp.java:37)
at java.util.stream.AbstractPipeline.pipeline(AbstractPipeline.java:336)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:142)
at java.util.Collection.addAll(Collection.java:505)
at java.util.ArrayList.addAll(ArrayList.java)
at java.util.stream.ReferencePipeline.into(ReferencePipeline.java:189)
at Main.map(Main.java:34)
at Main.extractDataTableRows(Main.java:39)
at Main.main(Main.java:29)

@Edwinの答えは最短ですが、これを実装するための「魔法」が割り当てられているため、デバッグと保守が最も困難です。これは単体テストでは問題ありませんが、製品コードの IMHO では望ましくありません。

 Exception in thread "main" ch.lambdaj.function.argument.InvocationException: Failed invocation of public java.lang.String[] Main$ContractLineItem.getDataTablesRow() on object Main$ContractLineItem@1d724f31 caused by: null
at ch.lambdaj.function.argument.Invocation.invokeOn(Invocation.java:70)
at ch.lambdaj.function.argument.InvocationSequence.invokeOn(InvocationSequence.java:91)
at ch.lambdaj.function.argument.InvocationSequence.invokeOn(InvocationSequence.java:85)
at ch.lambdaj.function.argument.Argument.evaluate(Argument.java:35)
at ch.lambdaj.function.convert.ArgumentConverter.convert(ArgumentConverter.java:36)
at ch.lambdaj.function.convert.ConverterIterator.next(ConverterIterator.java:37)
at ch.lambdaj.Lambda.convert(Lambda.java:986)
at ch.lambdaj.Lambda.extract(Lambda.java:1035)
at Main.extractDataTableRows(Main.java:49)
at Main.main(Main.java:27)
 Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:474)
at ch.lambdaj.function.argument.Invocation.invokeOn(Invocation.java:68)
... 14 more
 Caused by: java.lang.RuntimeException
at Main$ContractLineItem.getDataTablesRow(Main.java:85)
... 19 more

この構文は慣れるまでに時間がかかりますが、構文が強化され、定型コードの一部が削除されると、より読みやすくなる可能性があると思います。

Java 8 Lambda 対 LambdaJ 対 Guava 対 反復的アプローチの良い比較です元はロシア語なので、Google 翻訳を許してください ;)

于 2013-01-09T11:58:03.490 に答える
2

どうですか

List<String[]> items = extract(contractLineItems, on(ContractLineItem.class).getDataTablesRow());

LambaJ には、マッパーである extract という名前のメソッドが付属しています。lambdaj を使用したオブジェクトの変換に関するリファレンスも読むことができます。

于 2013-01-09T11:59:18.890 に答える