当前位置: 首页 > 面试题库 >

Java 8流反向顺序

端木志诚
2023-03-14
问题内容

一般问题:反向流的正确方法是什么?假设我们不知道流包含什么类型的元素,反转任何流的通用方法是什么?

具体问题:

IntStream提供了range方法来生成特定范围内的Integer IntStream.range(-range, 0),现在我想将其从0切换为负数将无法正常工作,也无法使用Integer::compare

List<Integer> list = Arrays.asList(1,2,3,4);
list.stream().sorted(Integer::compare).forEach(System.out::println);

与IntStream我会得到这个编译器错误

错误:(191,0)ajc:sorted()类型中的方法IntStream不适用于参数(Integer::compare)

我在这里想念什么?


问题答案:

对于产生反向的特定问题IntStream,请尝试如下操作:

static IntStream revRange(int from, int to) {
    return IntStream.range(from, to)
                    .map(i -> to - i + from - 1);
}

这样可以避免装箱和分类。

对于如何反转任何类型的流的一般问题,我不知道有“适当的”方法。我可以想到几种方法。两者最终都存储了流元素。我不知道在不存储元素的情况下反转流的方法。

第一种方法将元素存储到数组中,然后以相反的顺序将它们读出到流中。请注意,由于我们不知道stream元素的运行时类型,因此我们无法正确键入数组,这需要未经检查的强制转换。

@SuppressWarnings("unchecked")
static <T> Stream<T> reverse(Stream<T> input) {
    Object[] temp = input.toArray();
    return (Stream<T>) IntStream.range(0, temp.length)
                                .mapToObj(i -> temp[temp.length - i - 1]);
}

另一种技术是使用收集器将项目累积到反向列表中。这会在ArrayList对象的前面进行很多插入操作,因此正在进行大量复制。

Stream<T> input = ... ;
List<T> output =
    input.collect(ArrayList::new,
                  (list, e) -> list.add(0, e),
                  (list1, list2) -> list1.addAll(0, list2));

使用某种自定义数据结构可能会编写出效率更高的可逆收集器。

更新2016-01-29

由于这个问题最近引起了人们的关注,我认为我应该更新自己的答案以解决在前面插入的问题ArrayList。对于大量元素,这将是极其低效的,需要O(N ^ 2)复制。

最好使用ArrayDeque有效支持正面插入的。一个小皱纹是我们不能使用的三参数形式Stream.collect();它要求将第二个arg的内容合并到第一个arg中,并且在上没有“前添加所有”批量操作Deque。相反,我们使用addAll()将第一个arg的内容附加到第二个arg的末尾,然后返回第二个。这需要使用Collector.of()工厂方法。

完整的代码是这样的:

Deque<String> output =
    input.collect(Collector.of(
        ArrayDeque::new,
        (deq, t) -> deq.addFirst(t),
        (d1, d2) -> { d2.addAll(d1); return d2; }));

结果是aDeque而不是aList,但这不成问题,因为它可以轻松地以现在相反的顺序进行迭代或流式传输。



 类似资料:
  • 我有这个列表,我想按保留顺序订购,但我没有在自动完成辅助中找到任何函数 我也尝试过: 但是我有编译错误:

  • 问题内容: 我正在使用Java lambda对列表进行排序。 如何以相反的方式对其进行排序? 我看到了这篇文章,但是我想使用java 8 lambda。 这是我的代码(我用* -1)作为破解 问题答案: 您可以调整在Java中如何以降序对ArrayList 排序的方法中链接的解决方案通过将其包装在lambda中: 请注意, f2 是的第一个参数,而不是第二个,因此结果将相反。

  • 问题内容: 我想处理对象中的列表。我必须确保处理所有元素,以便收到它们。 因此l,我应该使用它吗? 还是只要不使用并行性就足以使用流? 问题答案: 你在问错问题。你正在询问而要按顺序处理项目,因此你必须询问订购。如果你有顺序的流并执行保证维持顺序的操作,则该流是并行处理还是顺序处理都没有关系;实施将维持秩序。 有序属性不同于并行与顺序。例如,如果你调用一个同时调用流将是无序在List返回的有序流。

  • 我想在Java对象中处理列表。我必须确保处理所有的元素,以便我收到他们。 因此,我是否应该对我使用的每个调用? 或者,只要不使用并行性,只使用流就足够了吗?

  • 问题内容: 表LIMIT 8、3中的SELECT ID 结果为8,9,10 但我需要10,9,8 你该怎么做?如果您添加“ ORDER BY ID DESC”,则得到3,2,1 问题答案: 将查询放入子选择中,然后在外部选择中颠倒顺序: 测试数据: 结果: 请注意,子查询中的ORDER BY是必需的,否则顺序是不确定的。感谢Lasse指出这一点!

  • 我想像下面这样对流进行反向排序,但是编译时错误为。有人能纠正这个吗