java - 使用 Java 8 集合流 API 堆栈

标签 java java-8 java-stream java-collections-api

我有一个方法,每次执行时都会生成一个对象,我需要颠倒获取它们的顺序。所以我认为最自然的做法是堆栈,因为它是 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应该首选的接口(interface)。

但是我会告诉你原因Stack不应该使用。

首先是 Java Doc。堆栈的自己说:

A more complete and consistent set of LIFO stack operations is provided by the Deque interface and its implementations, which should be used in preference to this class. For example:

Deque<Integer> stack = new ArrayDeque<Integer>();

JavaDoc .

那么 Stack 类有什么问题。

就像 Martin Fowler 在他的书中已经提到的那样 重构:改进现有代码的设计 在重构方法Replace Inheritance with Delegation, Stack 不应该从 Vector 继承。

One of the classic examples of inappropriate inheritance is making a stack a subclass of vector. Java 1.1 does this in its utilities (naughty boys!) [6, p. 288]

相反,他们应该使用如下图所示的委托(delegate), 这也是书上的。

参见此处:Replace Inheritance with Delegation

Replace Inheritance with Delegation

那么,为什么这是个问题:

因为堆栈只有 5 个方法:

  1. 流行音乐
  2. 是空的
  3. 搜索
  4. 尺寸

size()isEmpty() 继承自 Vector Vector 中的类和其他方法不使用。但是通过继承,其他方法被转发到 Stack 类,这是没有意义的。

福勒对这个问题说:

You can live with the situation and use convention to say that although it is a subclass, it's using only part of the superclass function. But that results in code that says one thing when your intention is something else—a confusion you should remove.

这伤害了 Interface Segregation Principle

上面写着:

CLIENTS SHOULD NOT BE FORCED TO DEPEND UPON INTERFACES THAT THEY DO NOT USE.


您可以查看Vector的源代码Stack类(class) 你会看到 Stack 类继承了 spliterator 方法 和 Vector 类中的 VectorSpliterator innerClass。

Collection 接口(interface)使用此方法来实现。流方法的默认版本:

default Stream<E> stream() {
  return StreamSupport.stream(spliterator(), false);
}

因此,请避免简单地使用 VectorStack 类。

[6] 重构:改进现有代码的设计 Fowler,Martin 1997 年

关于java - 使用 Java 8 集合流 API 堆栈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30387579/

相关文章:

java - 寻找服务器发送事件规范客户端的 Java 实现。

java - 尝试创建三个类并绘制蜡笔盒。如何在构造函数中绘制蜡笔?

java-8 - Optional.ifAbsentThrow()?

将函数返回值中的对象添加到列表时的Java 8 Stream异常处理

java - java中的byte[]实际上是如何存储数据的

java - 如何在android中暂停和恢复倒计时器

json - 使用 java 8 将 Map<Object, List<Object>> dataMap 转换为 json

Java 8 : AveragingDouble and mapping to object

java - 如何使用 Java Stream 根据输入文件中的字符将对象添加到二维数组

java - 如何在带有 lambda 表达式的 Java 8 中使用多个流和 .map 函数