オブジェクトを実行するたびにオブジェクトを生成するメソッドがあり、取得する順序を逆にする必要があります。だから私はそれがLIFOなので、それを行う自然な方法はスタックだと思った。
ただし、Java Stack は、新しいJava 8ストリーミングAPIではうまく機能しないようです。
私がこれをすると:
Stack<String> stack = new Stack<String>();
stack.Push("A");
stack.Push("B");
stack.Push("C");
List<String> list = stack.stream().collect(Collectors.toList());
System.out.println("Collected: " + list);
私が得る出力は:
Collected: [A, B, C]
LIFOの順序でストリームに出力しないのはなぜですか?これは、スタックからすべての項目を正しい(LIFO)の順序でリストにフラッシュする正しい方法ですか?
すでにコメントで述べられているように、私達は Deque
インターフェースを十分にテストしました。
しかし、 Stack
を使用しない理由を説明します。
最初に、Java Doc。of the Stackは次のように述べています。
より完全で一貫性のあるLIFOスタック操作のセットは、Dequeインターフェースとその実装によって提供され、このクラスよりも優先して使用する必要があります。次に例を示します。
Dequeスタック=新しいArrayDeque();
JavaDoc を参照してください。
それで、Stack
クラスの問題は何ですか。
Martin Fowlerが彼の本ですでに述べたようにRefactoring:Improving the Design of Existing Codeat the refactoring method 継承を委任で置き換える、スタックはベクターから継承しないでください。
不適切な継承の典型的な例の1つは、スタックをベクターのサブクラスにすることです。 Java 1.1はユーティリティでこれを実行します(いたずらな男の子!)[6、p。288]
代わりに、下の図のように本からの委任を使用する必要がありました。
ここも参照してください: 継承を委任に置き換える
では、なぜこれが問題なのでしょうか。
スタックには5つのメソッドしかないため:
サイズ
size()
およびisEmpty()
は Vector
クラスから継承され、 Vector
からの他のメソッドは使用されません。しかし、継承によって、他のメソッドはStack
クラスに転送されますが、これは意味がありません。
そしてファウラーはこの問題にこう言っています:
この状況に対処し、規則を使用して、サブクラスであるにもかかわらず、スーパークラス関数の一部のみを使用していると言うことができます。しかし、その結果、意図が他の何かであるときに1つのことを言うコード、つまり、取り除かなければならない混乱が生じます。
それは言う:
クライアントは、使用しないインターフェースに依存することを強制されるべきではありません。
Vector および Stack クラスのソースコードをチェックアウトすると、Stackクラスがspliterator
を継承していることがわかりますメソッドとVectorSpliterator
クラスのVector
innerClass。
このメソッドは、Collection
インターフェースが実装するために使用されます。ストリームメソッドのデフォルトバージョン:
default Stream<E> More ...stream() {
return StreamSupport.stream(spliterator(), false);
}
したがって、Vector
およびStack
クラスの使用は避けてください。
[6]リファクタリング:既存のコードファウラーのデザインの改善、1997年マーティン