当前位置: 首页 > 知识库问答 >
问题:

如何从排序流列表中连续查看最低元素

周兴朝
2023-03-14

我开始学习Java流,我想知道是否有可能只偷看流的第一个元素而不检索它。

例如,我有多个流,每个流都有按非降序排序的整数,我想得到所有整数的排序列表,所以我考虑使用< code>PrioirtyQueue

但是,为了获取PrioirtyQueue

例如,我有以下流。

[1, 2, 3, 5],
[0, 2, 4, 6]

我想写一个函数getNextInteger(),它处理排序流的列表。

每次我调用该方法时,它都会返回下一个最小的整数,因此,如果我调用该方法4次,结果可能是[0,1,2,2]

我想使用PriorityQueue按其第一个值对流进行排序,并检索最小的值,如果流不为空,则重新排队。


共有2个答案

刘元青
2023-03-14
匿名用户

我想知道是否可以只查看流的第一个元素而不检索它。

偷看是一个中间操作,就像地图、排序等一样。它们不会导致流开始传递数据。为此,需要终端操作(如 reduce、forEach 或 collector 等)来启动流式处理过程。

这也允许人们在不存储任何数据的情况下执行以下操作。如果是这样,第一个语句(系列)将永远不会完成,因为它需要无限存储,因为没有限制方法。

IntStream series = IntStream.iterate(0, i->i+1);
IntStream first10 = series.limit(10);
int[] toArray = first10.toArray();

System.out.println(Arrays.toString(toArray));

指纹

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

在上面的示例中,< code>toArray()是启动流的终端操作。一旦完成,流就被耗尽,并且上述赋值(例如< code>series,first10)都不能再次使用。

柯捷
2023-03-14

Stream是对数据源进行迭代的一种方式,它旨在处理数据,而不是存储它。

因此,你的问题本质上是不正确的。简短的回答是不。

它不是数据结构,您不能以与ListQueue中的元素相同的方式访问流中的元素。

看看留档:

集合和流虽然有一些表面上的相似之处,但它们有不同的目标。集合主要关注对其元素的有效管理和访问。相比之下,流不提供直接访问或操作它们的元素的方法,而是声明性地描述它们的源以及将在该源上执行的计算操作。

正如我所说,stream是迭代的意思,但流管道也不同于IteratorIterator允许一个接一个地检索元素。相反,流管道要么被执行并产生一个结果(作为单个值或值的html" target="_blank">集合)并将被关闭,要么不被执行。这将取决于stream是否有终端操作。

例如,这个流是有效的,它可以很好地编译,但不会被执行:

Stream.of("a", "b", "c").map(String::toUpperCase);

因为它缺少一个终端操作。

每个流都应该有一个源和一个终端操作,触发管道的执行并产生结果。用于转换流的中间操作,如<code>map(),是可选的。

如果不处理流,就无法从流中获取数据。一旦处理完毕,就不能再使用了。

作为解决此问题的可能方法,您可以考虑使用一个对象包装流,该对象将分别维护来自流源的第一个元素和流本身。

public record StreamWrapper(int first, IntStream stream) {}

可以使用这种方法,通过单个值比较流就足够了,该值应在生成流的同时从流源中提取(如果流源允许)。

我想写一个函数getNextInteger(),它处理一个排序流的列表。

每次我调用该方法时,它都会返回下一个最小的整数,因此,如果我调用该方法4次,结果可能是[0,1,2,2]

该任务不适用于流。除非您可以忽略每个流中的数据已经排序的事实。

如果我们将所有的流合并成一个流并应用排序,就不会像一开始看起来的那样造成巨大的性能损失。为了对数据流进行排序,将所有元素转储到一个数组中,在这种情况下,该数组将由排序后的子数组组成。因为引用类型的数组将使用Timsort排序,所以算法实现将发现所有这些排序的块。也就是说,对由部分排序的子数组组成的数组进行排序不同于从头开始对所有这些数据进行排序。因此,我们可以将其视为一种可能的选择:

List<Stream<Integer>> streams =
List.of(Stream.of(1, 3), Stream.of(5), Stream.of(2, 6, 7),
        Stream.of(4, 9, 10), Stream.of(8));
        
streams.stream()
    .flatMap(Function.identity())
    .sorted()
    .forEach(num -> System.out.print(num + " "));

将产生输出:

1 2 3 4 5 6 7 8 9 10 

如果打印(或存储到集合中)按升序排序的整体数据似乎不令人满意,并且由于方法调用的结果,您坚持只检索单个值,我将重申不可能从流中一个接一个地连续获取值。

为此,您需要一个<code>迭代器

但是,如果提供的流操作不提供所需的功能,基流。迭代器()基流。spliterator()操作可用于执行受控遍历。

您可以实现一个自定义迭代器,该迭代器将利用引擎盖下的优先级队列。

我假设流的类型实现了可比较并且流被排序(如您提供的示例中所示)。

迭代器:

public class QueueBasedIterator<T extends Comparable<T>> implements Iterator<T> {
    private Queue<IteratorWrapper<T>> nextValues = new PriorityQueue<>();
    private List<Iterator> iterators = new ArrayList<>();
    
    @SafeVarargs
    public StreamBasedIterator(Stream<T>... streams) {
        this.iterators = Stream.of(streams).map(Stream::iterator)
            .collect(Collectors.toList());
        
        for (int i = 0; i < iterators.size(); i++) {
            Iterator<T> iterator = iterators.get(i);
            if (iterator.hasNext()) 
                nextValues.add(new IteratorWrapper<T>(i, iterator.next()));
        }
    }
    
    @Override
    public boolean hasNext() {
        return !nextValues.isEmpty();
    }
    
    @Override
    public T next() {
        if (nextValues.isEmpty()) {
            throw new NoSuchElementException();
        }
        
        IteratorWrapper<T> next = nextValues.remove();
        Iterator<T> iterator = iterators.get(next.getPosition());
        if (iterator.hasNext())
            nextValues.add(new IteratorWrapper<T>(next.getPosition(), iterator.next()));
        
        return next.getValue();
    }
}

IteratorWrapper:

class IteratorWrapper<T extends Comparable<T>> implements Comparable<IteratorWrapper<T>> {
    private T value;
    private int position;
    
    public IteratorWrapper(int position, T value) {
        this.value = value;
        this.position = position;
    }
    
    public T getValue() {
        return value;
    }
    
    public int getPosition() {
        return position;
    }
    
    @Override
    public int compareTo(IteratorWrapper<T> o) {
        return this.value.compareTo(o.value);
    }
}

main()-demo

public static void main(String[] args) {
    QueueBasedIterator<Integer> iterator =
        new QueueBasedIterator<>(Stream.of(1, 3), Stream.of(5), Stream.of(2, 6, 7),
                                 Stream.of(4, 9, 10), Stream.of(8));
    
    while (iterator.hasNext()) {
        System.out.print(iterator.next() + " ");
    }
}

输出

1 2 3 4 5 6 7 8 9 10
 类似资料:
  • 问题内容: 我想按从高到低的顺序进行排序。 问题答案: java.util.Collections.sort(列表,比较器) 您将需要写一个

  • {4,5,1,5,7,6,8,4,1},答案是5。 对于第一个例子,子数组{5,3,1,4,2}排序后可以形成连续序列1,2,3,4,5,它们是最长的。 对于第二个示例,子数组{5,7,6,8,4}是结果子数组。

  • 我一直在尝试将更多的函数式编程融入到我所做的事情中,因为我编写的代码具有无副作用的性质,并且在并发代码中具有实用性。我遇到了需要过滤掉java流的连续元素的情况,并且没有比简单的旧命令方法更好的函数方法了。假设我有一个记录参数的程序,我想过滤掉两个连续的元素。例如,。我在日志中想要的是。 我提出了几种方法,但没有一种方法比使用for循环更容易理解,该循环索引了我需要过滤掉的内容。 这似乎是一件很平

  • 我有一张叫‘宽床单’的桌子。这是一个班级学生所有学科总分的汇总之处。 通过此查询获得了每个主题的总数 并用此显示 而总体总数显示为 一切都很顺利,直到我不得不对表格进行排序,从总分最高到最低。表现在应该如下所示: 我真的被困住了。我从这里怎么走? 好吧,按照@titi的建议,我做了一个group_by查询,得出了这样的结果: 如果这是正确的,我如何显示它?

  • lindex 返回名称为key的list中index位置的元素,例如: redis 127.0.0.1:6379> lindex mylist5 0

  • 我以前见过一些最长的连续序列问题,比如查找递增子序列。我现在正在努力进一步发展我的技能。给定一个整数数组,我想找到一个最长的连续序列,其中各个子序列中所有元素的差值小于一个给定的数字,例如3。一个例子是[10,11,12,15,13],其中只有前三个元素满足条件。此外,我还想返回给定数组中第一个和最后一个元素的索引。 我想做两个函数;get_first_element(arr)和get_last_