2009-06-26 13 views
17

私は、Java標準コレクションライブラリのAPI矛盾を理解しようとしています。Java ListインターフェイスがgetLast()をサポートしないのはなぜですか?

最後のアイテムを取得するメソッドはListまたはAbstractListにありませんが、sizeおよびgetIndex()を使用してそのアイテムをシミュレートできます。

ただし、LinkedListはその機能をサポートしています。

インターフェイスでこのメソッドをサポートしないと決定した理由は何ですか?

+0

コードで数回それを処理した後、メンテナンスプログラマーをAPIデザイナーに怒らせるようにしていると確信しています。 :-) Greenfieldのプログラマーは、Listの代わりにLinkedListを渡してしまうので、getLast()を使うことができます。メンテナンス担当者は、ArrayListがより適切であることを理解しています。リストの最初の場所にあるはずのこれらすべての指定されたLinkedListを処理する必要があります(リストインターフェイスのこの1つの重大なエラーを除いてはおそらく...) –

答えて

19

java.util.ListインターフェイスはgetLast()をサポートしていません。なぜなら、デザイナーは「最小限のインターフェイス」を使用していたからです。定義されたメソッドの数が最小限に抑えられているため、理解しやすく、素早く学習することができます。

これは、一般的な操作(例えば、getLast())を行う方法を提供しようと試みる(ヒューマンインタフェース)(Ruby array classで使用される)と対照的です。このようなリストのような基本的な概念には多くの用途があるため、より大きなインターフェースが得られる傾向があります。

詳細については、Martin FowlerのMinimal InterfaceおよびHumane Interfaceの説明を参照してください。 LinkedListのは、javadocを引用し、getLast()などをサポートしています理由として

を... LinkedListのクラスを取得するための均一という名前のメソッドを提供し、リストの最初と最後の要素を削除して挿入。これらの操作では、リンクリストをスタック、キュー、または両端キュー(両端キュー)として使用できます。

一般的なリストは、これらの特定の使用例では適切ではないと思われました。

Java Collections API(Joshua Bloch)の主要デザイナーの洞察として、彼はthis list of API design maximsを提供しています。そのうち、この質問に最も関連があります:APIを

初期の草案は、典型的には、1ページクラスとメソッドのシグネチャと1行の説明を、短くする必要があります。これにより、最初に正しく取得しなかった場合でもAPIの再構成が容易になります。

疑わしい場合は除外してください。 API設計の基本的な定理があるならば、これはそれです。これは、機能、クラス、メソッド、およびパラメータにも等しく適用されます。 APIのあらゆる側面はできるだけ小さくする必要がありますが、小さくする必要はありません。後で追加することはいつでも可能ですが、削除することはできません。概念的な重みを最小化することは、クラスまたはメソッドの数よりも重要です。

APIに実装の詳細は無料で保存してください。彼らはユーザーを混乱させ、進化の柔軟性を阻害します。実装の詳細が何であるかは必ずしも明らかではありません。過剰指定に注意してください。

アクセシビリティを最小限に抑えます。疑わしいときは、それを非公開にしてください。これにより、APIが簡素化され、結合が減少します。

API設計の決定によるパフォーマンスの影響を考慮しますが、パフォーマンスを向上させるためにAPIを歪ませないでください。幸運なことに、良いAPIは一般的には速い実装に向いています。

彼はまた述べしかし:

は、クライアントはライブラリが行うことができます何もしないでください。このルールに違反すると、クライアントで定型的なコードになります。これは面倒でエラーが発生しやすいです。

これは、デザインガイドラインによく矛盾があり、API設計者の仕事の最も難しい部分が、これらの競合のバランスをとることを示しています。

+8

良い説明。私になぜisEmptyメソッドがあるのか​​不思議に思う。 – peskal

+0

@peskal Java 8では、メソッド参照としてisEmptyを使うことができます。 –

+0

@ThorbjørnRavnAndersenしかし、Java 8のはるか前に存在していました; – Joffrey

2

インタフェースの目標は、可能な限り少ない数のパブリックメソッドを使用可能性を最大限に提供することです。サポートする方法が少ないほど、優れています。あなたが言ったように、これは導き出すことができるので、getLast()メソッドはありません。

LinkedListは、具体的な実装であり、したがってこれらの問題はありません。

編集:Skaffmanが指摘しているように、これはインターフェイスのメインの目標ではありません。これは、このインタフェースの実装を容易に維持できるようにする、より多くの目的です。インタフェースの主な目的は、具体的な実装をそれを使用するオブジェクトから切り離すことです。

+8

いいえインタフェースの目的は、インタフェースから実装を分離することです。操作の種類はそれとは関係ありません。 – skaffman

+0

私は同意しているかどうかはわかりませんが、誰かがリストの最後のアイテムをどのくらい出すかによって異なります。 – Uri

+1

一般的なgetFirst()getLast()インタフェースメソッドはO(1)ではないので、組み込みのLinkedList/ArrayListとは別のリスト実装が可能ですか? – akarnokd

5

通常、Big-Oの要件で各関数を指定したいと考えていたため、すべてのリストでgetLast()を効率的に実装できなかったと考えられます。だから彼らはBig-Oの約束で各レベルでそれを紹介します。

これは単に見落としただけかもしれませんし、一般的ではないと感じていて、必要な場合はsize/getIndexで取得できます。

+3

私は時にはArrayListにも少なくともそれを追加したかったと思います。 arraylist.get(arraylist.size()-1)を何度も繰り返し書くことは、ある種の定型文です。 – akarnokd

+1

パブリッククラスMyArrayList ArrayListを拡張します {public getLast(){return get(size - ) - 1};}} – Charlie

+2

@Charlie:リストインターフェイスを使用していない限り、実装。 – Uri

1

あなたが言ったように、それはインデックスに基づいているので、あなたはgetIndex()で最後のものを得ることができます。個人的に私はそれを置く理由がない(あなた自身で書くことができるので)。

LinkedListは配列ベースではありませんが、インデックスはありませんが、そのようなメソッドを提供することは理にかなっていますが、最後のアイテムを知る必要があることもあります。

0

getLast()を一方向リンクリストに実装できませんでした。一方向リンクリストのgetIndex()は、効率的な意味を持つように、最初からリスト全体をスキャンするでしょう。

+1

フィールドに最後の要素が格納されていない限り。 getSize()はどのように実装されていると思いますか? –

+0

これは、javaのLinkedListがダブルリンクされているか、リンクされている単一のケースであるため、リストの最後にO(1)を追加するための最後の要素への参照を保持しているだけです。 – akarnokd

1

getLast()メソッドは、LinkedListが実装するDequeインターフェイスからのものです。配列をバックアップしたい場合は、ArrayDequeを使うことができます。 LinkedListのような実装では複数のインタフェースを実装することができますが、別の抽象データ型を別々のインタフェースに分けたいので、Listインタフェースの一部ではないと思います。

+0

DequeインタフェースはJava 6でのみ導入されました。(1.2で導入された)いくつかのバージョンでLinkedListクラス(getLast()メソッド) –

0

Listインターフェイスには、そのタイプの簡易メソッドはありません。いいえ、getFirst()またはgetLast()。それは厳密にインデックスベースです。 LinkedListはパフォーマンス上の理由から可能な限りインデックスに基づく検索を避ける方法が必要です。したがって、getLastは実際には便利なメソッドではなく、最適化です。

私はデザイナーがメソッドの量を減らしたいと思っているので、多くの便利なメソッドを追加することはできませんでした。

+1

LinkedListの実装を見ると、インデックスに基づくロックアップの最適化が含まれています。インデックスがリストの半分のサイズよりも後であれば、最後にトラバーサルが開始され、後方に移動します。この方法でget(size - 1)は実質的にgetLast()と同じ時間コストを持ちます。 – akarnokd

+0

@ kd304、これはLinkedListに最適ではないインデックスベースのルックアップの一般的なケースに対処しない実装の詳細です。 LinkedListには、特定のインデックスに基づく検索が高速になるという契約はありません。 – Yishai

関連する問題