Java:如何反转ArrayList中每N个元素的顺序

问题描述 投票:0回答:5

我有一个包含数千行单词的输入文本文件,我想在其中写入输出文件,并在其中反转每 10 行的顺序。我已经迭代了整个文本文件,并将其存储在

ArrayList<String> array
中,现在我正在尝试弄清楚如何反转整个 ArrayList 中每 10 行的顺序。

例如输出应该是这样的: Line : 10, 9, 8, 7 ...... 1, 20, 19, 18, 17.....11, 30, 29, 28, 27。 ....21 等等,直到我对整个文本文件(存储在 ArrayList 中)完成此操作。下面是我一直用来尝试反转这些行的代码部分。

   for(int i = array.size()-1; i >= array.size()-10; i--){ 
     array.add(array.get(i));
   }

   for (String text : array) {
            w.println(text);
        }

 }

到目前为止,我仅读取并反转输入文件的最后 10 行,并将其写入输出文件。我一直在寻找一种方法来在整个数据集中迭代地实现这种类型的模式,以确保我不会遇到索引越界错误。

java arraylist iteration reverse readfile
5个回答
4
投票

使用简单的流式传输方法。这基本上是当前的解决方案,每十行应用一次,而不是最后一次。

读十行。
  1. 反转这些行
  2. 1
  3. 写出十个颠倒的线条。
  4. 重复直到处理完整个文件。
  5. 唯一的边缘情况是当文件不是 10 行的倍数时,在最后执行适当的操作。

同样的流式处理方法可用于创建一个

new

each-10 反转列表。当尝试改变原始列表时,它只会“变得复杂”。


1

写入输出时,可以通过向后迭代十行列表来组合步骤 2 和 3。


1
投票

如果它已在内存中,则在
    ArrayList
  1. 中,只需更新该列表即可。
    如果内存中尚未存在,请一次处理 10 行。
  2. 这允许处理无限大的数据而不会耗尽内存。

  3. 选项 1。

List<String> list = new ArrayList<>(); // code filling list for (int i = 0; i < list.size(); i += 10) { int endOfBlock = Math.min(i + 10, list.size()); for (int j = i, k = endOfBlock - 1; j < k; j++, k--) { String temp = list.get(j); list.set(j, list.get(k)); list.set(k, temp); } }

选项 2。

try (BufferedReader in = new BufferedReader(new FileReader(inFile)), PrintWriter out = new PrintWriter(new FileWriter(outFile))) { String[] buf = new String[10]; int len = 0; for (String line; (line = in.readLine()) != null; ) { buf[len++] = line; if (len == 10) { while (len > 0) out.println(buf[--len]); } } while (len > 0) out.println(buf[--len]); }



1
投票

for (int i = 0, size = array.size(); i < size; i += 10) for (int from = i, to = Math.min(i + 10, size); from < to;) Collections.swap(array, from++, --to);



0
投票

while(counter<array.size()+10) int counter = 9; //since index 9 is the 10th line for(int i=counter; i>counter-10; i--){ if(i<array.size()){ array.add(array.get(i)); } } counter+=10; } for (String text : array){ w.println(text); }

我在这里唯一担心的是,您似乎只是继续添加到现有数组,而不是重新排序或将元素添加到新数组?


0
投票
JEP 461:Stream Gatherers

Java 22 预览语言功能的基于流的解决方案: // [1, 2, 3, ..., 21, 22] List<String> lines = IntStream.range(1, 22).mapToObj(Integer::toString).toList(); // [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 22, 21] List<String> output = list.stream() .gather(Gatherers.windowFixed(10)) .flatMap(window -> window.reversed().stream()) .toList();

这使用新的 

Stream.gather

 方法和新的内置 
Gatherers.windowFixed
 收集器将列表一次分为 10 个项目。
演练

    List<String>
  1. 转换为
    Stream<String>
    // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22]
    lines.stream()
    
    将元素收集到具有 10 个元素(或更少,如果位于流末尾)的窗口中。结果是 
  2. Stream<List<String>>
  3. // [[1,2,3,4,5,6,7,8,9,10], [11,12,13,14,15,16,17,18,19,20], [21,22]]
    .gather(Gatherers.windowFixed(10))
    
    翻转每个窗口,然后将其压平。这将转换回 
  4. Stream<String>
  5. // [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 22, 21]
    .flatMap(window -> window.reversed().stream())
    
  6. Stream<String>
  7. 转换为
    List<String>
    .toList()
    
    
    
  8. Java文档

Gatherer

将输入元素流转换为输出元素流的中间操作,可以选择在到达上游末尾时应用最终操作。 […]

[…]

聚集操作的例子有很多,包括但不限于:将元素分组(窗口函数);对连续相似的元素进行去重;增量累加功能(前缀扫描);增量重新排序功能等。类

Gatherers

提供了常见收集操作的实现。

Stream.gather

返回一个流,其中包含将给定收集器应用于该流的元素的结果。

Gatherers.windowFixed



返回一个收集器,它将元素收集到固定大小的窗口中——遇到有序的元素组。如果流为空,则不会生成任何窗口。最后一个窗口包含的元素可能少于提供的窗口大小。

示例:

// will contain: [[1, 2, 3], [4, 5, 6], [7, 8]] List<List<Integer>> windows = Stream.of(1,2,3,4,5,6,7,8).gather(Gatherers.windowFixed(3)).toList();

    
© www.soinside.com 2019 - 2024. All rights reserved.