Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何按相反顺序对IntStream进行排序_Java_Java 8_Java Stream - Fatal编程技术网

Java 如何按相反顺序对IntStream进行排序

Java 如何按相反顺序对IntStream进行排序,java,java-8,java-stream,Java,Java 8,Java Stream,我正在使用BufferedReader从.txt文件中读取数字。我想颠倒这个蒸汽中元素的顺序,这样当它们被收集时,它们将从最高到最低排列。我不想在数组构建之后进行排序,因为我不知道其中可能包含多少元素,我只需要最高的N个元素 in = new BufferedReader(reader); int[] arr = in.lines() .mapToInt(Integer::parseInt)

我正在使用
BufferedReader
从.txt文件中读取数字。我想颠倒这个蒸汽中元素的顺序,这样当它们被收集时,它们将从最高到最低排列。我不想在数组构建之后进行排序,因为我不知道其中可能包含多少元素,我只需要最高的N个元素

in = new BufferedReader(reader);
                int[] arr = in.lines()
                        .mapToInt(Integer::parseInt)
                        .sorted()
                        .limit((long) N)
                        .toArray();

由于反向顺序不是自然顺序,
sorted()
不能用于反向顺序排序。如果避免使用
IntStream
,而是使用
Stream
,则可以使用
Collections.reverseOrder()
以与自然顺序相反的顺序对流进行排序。然后您可以调用
mapToInt
并在最后转换为
int[]

int[] arr = in.lines()
            .map(Integer::valueOf)  // Extract Integer, not int
            .sorted(Collections.reverseOrder())  // On Stream<Integer>
            .limit(N)
            .mapToInt(i -> i)       // map Integer to int
            .toArray();
int[]arr=in.lines()
.map(Integer::valueOf)//提取整数,而不是int
.sorted(Collections.reverseOrder())//在流中
.限制(N)
.mapToInt(i->i)//将整数映射到int
.toArray();

很难说
.sorted().limit((long)N).toArray()
在某些情况下是否会得到优化(它依赖于实现,但我不希望看到Oracle当前的实现),但在这种特殊情况下,源流是一个大小未知的流,这使得优化的可能性更小

如果您想安全起见,您可以适应高效地获得n个最大流数。您所要做的就是颠倒顺序:

public static IntStream maxValuesDescending(IntStream source, int limit) {
    TreeMap<Integer,Integer> m=new TreeMap<>(Comparator.reverseOrder());
    source.forEachOrdered(new IntConsumer() {
        int size, min=Integer.MIN_VALUE;
        public void accept(int value) {
            if(value<min) return;
            m.merge(value, 1, Integer::sum);
            if(size<limit) size++;
            else m.compute(min=m.lastKey(), (k,count)->count==1? null: count-1);
        }
    });
    if(m.size()==limit)// no duplicates
        return m.keySet().stream().mapToInt(Integer::valueOf);
    return m.entrySet().stream().flatMapToInt(e->{
        int value = e.getKey(), count = e.getValue();
        return count==1? IntStream.of(value): IntStream.range(0, count).map(i->value);
    });
}

但不需要创建数组,因为可以对结果使用任意
IntStream
操作。此解决方案最多只能保存
N
个值,如果存在重复值,则保存的值会更少,因为它只保存不同的值及其计数。

尝试在排序前对值求反,然后在排序后对值求反(返回正常值):

in = new BufferedReader(reader);
int[] arr = in.lines()
              .mapToInt(Integer::parseInt)
              .map(i -> -i).sorted().map(i -> -i)
              .limit((long) N)
              .toArray();

使用Instream时,您实际上是在处理primitive,而且您的手很紧(您仅限于自然排序,无法定义自定义比较器。您有两种解决方案:

  • 坚持原始流,想出@normanrz提出的方法

  • 或者,您可以转换为整数(box)并使用各种解决方案,如下面的一个解决方案(但请注意,这种装箱和取消装箱可能会导致性能问题)


如果您知道不会有任何
Integer.MIN\u值
值,您可以添加一个步骤来映射
i->(-i)
Integer.MIN\u值
限定非常重要,因为
Integer.MIN\u值==(-Integer.MIN\u值)
)。另外,您知道排序限制组合是否已优化吗?因为如果未优化,则很有可能
sorted()
无论如何都要将它们存储在内存中,在这种情况下,您最好获取该数组并读取N个最大元素。@yshavit我认为您对排序限制组合的看法是正确的,它必须将其存储在某个中间容器中。它肯定必须将其存储在某个容器中。问题是,排序步骤是否足够聪明,可以知道在它后面有一个限制步骤?如果是这样,容器可能只有N个大的元素,每个新元素要么被删除,要么被推出一个以前存在的元素。如果流真的那么聪明,那么就做一些聪明的事情(就像你要求做的那样)可能绝对值得。如果不值得,那么你就不会真正节省太多。我认为
I->I
可能是
Integer::intValue
,对吗?@yshavit是的,
Integer::intValue
可以替换那里的
I->I
。很酷的技巧,尽管如果输入包含
Integer.MIN\u VALUE
@TagirValeev,你不能然后切换到
.map(i->~i)
而不是
.map(i->-i)
@OlivierGrégoire,是的,我知道。我差不多一年前就用过这个技巧了。
in = new BufferedReader(reader);
int[] arr = in.lines()
              .mapToInt(Integer::parseInt)
              .map(i -> -i).sorted().map(i -> -i)
              .limit((long) N)
              .toArray();
int[] sortedArray = IntStream.of(costs).boxed()
                              .sorted(Collections.reverseOrder())
                              .mapToInt(value -> value.intValue()).toArray();