5

a があり、の先頭に要素を追加しjava.util.List listて new を作成したいとします(つまり、cons andが必要です)。たとえば、Listelist elistlist

[1,2,3,4]

eあり5、次にcons(e,list)なる

[5,1,2,3,4]

と の要素をlist共有cons(e,list)することlistは問題ありませんが、変更しないでください。

を実装するための最も簡単かつ/または最も効率的な方法はcons何ですか? 結果が変更できなくても問題ありません。Google Collections Library の使用は許可されています。

の場合listcom.google.common.collect.ImmutableList?

4

10 に答える 10

8
public static<T> List<T> cons(List<T> list, T t) {
    ArrayList<T> result = new ArrayList<T>(list);
    result.add(0, t);
    return result;
}

コメントに応じて編集: 質問で「cons を実装する最も簡単かつ/または最も効率的な方法」が求められたため、「最も単純」にしました。もっと効率的な方法があることを知っても驚かないでしょう。リストの前に要素を配置することは、別の有効なアプローチであり、最初に正しいサイズを割り当てると、おそらくパフォーマンスが向上する可能性があります。時期尚早の最適化は諸悪の根源です。

于 2009-05-05T18:35:48.663 に答える
7

Clojureは、そのような Lisp 的なものを提供します。ほとんどの人は言語に Clojure を使用することを考えていますが (私のように)、Clojure ライブラリはすべて実際の Java コードであり、必要に応じて Java のデータ構造を特別なライブラリとして使用することもできます。そうすれば、cons などを実行できるようになり、Clojure が使用する不変性が得られます。Clojure のデータ構造体は、同等の Java 型も実装しています。

別の方向からの単なる考え。

于 2009-05-05T18:45:20.513 に答える
4

あなたが本当に探している答えはこれだと思います:

http://functionaljava.googlecode.com/svn/artifacts/2.20/javadoc/fj/data/List.html

メソッドも呼び出されconsます。

私はこのライブラリの経験がありません。先日聞いたばかりです。私はそれが良いことを願っています!

于 2009-11-06T10:11:05.630 に答える
4

効率的な解決策は、独自の List 実装を作成し、遅延委任することです。変更できない場合は、それほど問題にはなりません。ファクトリ メソッドを介して作成された場合、引数 List が RandomAccess を実装するかどうかに応じて、2 つの異なる基になる実装のいずれかを使用することもできます。

最も単純なケース (これがコンパイルされるかどうかを確認していない、健全性チェックがないなど):

class ConsList<E> extends AbstractList<E>
{
    private final E first;
    private final List<E> rest;

    ConsList( E first, List<E> rest )
    {
        this.first = first;
        this.rest = rest;
    }

    public int get( int index )
    {
        return (index == 0) ? first : rest.get( index - 1 );
    }

    public int size()
    {
        return rest.size() + 1;
    }
}

他のメソッドのいくつかをより効率的にすることができると確信しており、代わりに AbstractSequentialList を拡張することでシーケンシャル ケースをより適切に処理できます。

于 2010-04-14T02:03:53.447 に答える
3

これはあまり知られていませんが、Sun の javac コンパイラ API には、append()や などのメソッドを使用して新しい不変リストを返す不変リストの実装が含まれていますprepend()。それを使用するtools.jarには、クラスパスと次の import ステートメントが必要です。

import com.sun.tools.javac.util.List;

サンプルコード:

final List<Integer> list = List.of(6, 7);
System.out.println(list);

final List<Integer> newList =
    list.prepend(5)                       // this is a new List
        .prependList(List.of(1, 2, 3, 4)) // and another new List
        .append(8)                        // and another
        .reverse();                       // and yet another
System.out.println(newList);

System.out.println(list == newList);

System.out.println(list.getClass());
System.out.println(newList.getClass());

出力:

6,7
8,7,6,5,4,3,2,1
false
クラス com.sun.tools.javac.util.List
クラス com.sun.tools.javac.util.List

これは内部 API であり、本番環境では使用しないでください。

注:CollectionおよびListインターフェース ( など)のすべての標準の変更可能なメソッドは、明らかにadd() addAll()throwです。UnsupportedOperationException

参照:

于 2011-02-15T16:29:46.847 に答える
2

LinkedList は、リストの先頭にアイテムを挿入する最も効率的な方法でしょうか?

Javaに付属のLinkedListクラスを使用するだけです

于 2009-05-05T22:20:48.467 に答える
2

CompositeCollectionを使用できますか?

public Collection cons(Collection c1, Collection c2)
{
    CompositeCollection cons = new CompositeCollection();
    cons.addComposited(c1);
    cons.addComposited(c2);
    return cons;
}

これは、パラメーターの 1 つが不変であり、元のコレクション c1 および c2 によって引き続きサポートされているかどうかの影響を受けません。

必要な場合は、Listおそらく次のことを行います。

public List cons(Collection c1, Collection c2)
{
    ArrayList cons = new ArrayList(c1.size() + c2.size());
    cons.addAll(c1);
    cons.addAll(c2);
    return cons;
}
于 2009-05-05T18:26:36.470 に答える
2

私は 2 セントを投じて、誰かがもっとエレガントなものを思い付くかどうかを確認します。一般的なケースでは:

<E> List<E> cons(E e, List<E> list) {
    List<E> res = Lists.newArrayListWithCapacity(list.size() + 1);
    res.add(e);
    res.addAll(list);
    return res;
}

(これImmutableListがどれほど効率的かはわかりません):

<E> ImmutableList<E> cons(E e, ImmutableList<E> list) {
    return ImmutableList.<E>builder()
                        .add(e)
                        .addAll(list)
                        .build();
}
于 2009-05-05T19:10:29.393 に答える
0

Iterable しかない場合の別のバリエーション。

public static <E> List<E> cons(E e, Iterable<E> iter) {
   List<E> list = new ArrayList<E>();
   list.add(e);
   for(E e2: iter) list.add(e2);
   return list;
}

public static <E> List<E> cons(Iterable<E>... iters) {
   List<E> list = new ArrayList<E>();
   for(Iterable<E> iter: iters) for(E e1: iter1) list.add(e1);
   return list;
}
于 2009-05-07T19:57:11.167 に答える