【问题标题】:Moving ArrayList element to the last position in the List?将 ArrayList 元素移动到列表中的最后一个位置?
【发布时间】:2017-02-16 13:45:15
【问题描述】:

在以下方法中,我有一个 ArrayListStrings

我检查这些字符串中的任何一个是否在 txt 文件中(checkIfWordIsInTextFile 方法)。

如果一个字符串在这个列表中,我想把它last放在列表中,然后返回重新排序的列表。

我正在尝试使用 set 方法,但我不确定如何将字符串设置为列表中的 最后一个元素

当前方法:

 public List<String> placeParentsLastInLineItemList(List<String> listToReorder){

    for(String string: listToReorder){

       if(checkIfWordIsInTextFile(string)==true){
          listToReorder.set(,string); //how to set the string to the last element in list?
       }

    return listToReorder;
 }

【问题讨论】:

  • 删除后重新添加
  • 使用迭代器
  • 此时没有安装java,所以我不能尝试发布解决方案..但我有一些想法:创建一个默认的for循环(for(int i = 0; i
  • 所以我只是删除它并重新添加它,所有这些都在我原来的 for 循环中?

标签: java arraylist


【解决方案1】:

使用新的List 实例作为结果:

public List<String> placeParentsLastInLineItemList(List<String> listToReorder) {
    List<String> inFileList = new ArrayList<>();
    List<String> notInFileList = new ArrayList<>();
    for (String string : listToReorder) {
        (checkIfWordIsInTextFile(string)? inFileList: notInFileList).add(string);
    }
    return joinLists(notInFileList, inFileList);
}

private List<String> joinLists(List<String> list1, List<String> list2) {
    List<String> result = new ArrayList<>(list1);
    result.addAll(list2);
    return result;
}

该方案的优点还在于没有修改输入参数listToReorder的副作用。

【讨论】:

  • 创建一个完整的集合,只是为了将一个项目移动到现有项目的末尾?
  • @RossDrew 看不出有什么问题。但是这个带有foreach 的解决方案比没有它更清晰。没有任何理由,没有必要进行初步优化。
  • 这不是优化,只是很好的编码。仅仅为了移动单个项目而创建一个集合的完整副本是一种浪费。
  • Simple 是删除一个元素并将其添加到末尾。这很复杂。实际上如此复杂,以至于您设法弄乱了逻辑。它不起作用。它构建一个仅包含文件中元素的字符串。
  • 仍然相信这是更简单的解决方案?
【解决方案2】:

最简单的解决方案(适合初学者)

ArrayListList 默认 add() 行为根据定义添加到列表的末尾。所以:-

listToReorder.add(string)

您需要将其从原来的位置移除,所以不要使用 for-each 循环,使用索引,然后当你找到它时:-

listToReorder.remove(i);

...在重新添加到末尾之前,所以:-

for (int i=0; i<listToReorder.size(); i++){
  String item = listToReorder.get(i);

//NOTE: '==true' isn't required if the method returns a boolean
  if(checkIfWordIsInTextFile(item)){ 
//As per  @rishi007bansod suggestion: If we remove an item, then the next item will be shifted into this index & effectively skipped.  Therefore we want the index not to change this time around so decrement i after usage
    listToReorder.remove(i--);
    listToReorder.add(item);
  }
}

其他选项

  • 根据@Andriy Kryvtsuns 的回答,您可以创建一个新的临时列表并按照您想要的顺序重新创建该列表,但这会产生复杂的代码。另一个问题是您不知道传入了 List 的哪个实现,如果传递了 LinkedList 并且 remove() 可以比线性时间更快地运行,则创建整个列表可能效率低下.

更多高级选项

  • 您可以使用 for-each 循环(如 @Ash French),但您需要使用 Iterator,因为 for-each 循环会限制您编辑正在循环的集合

  • 您可以获取所有 Java 8 并使用 lambda,按照 @Mad Matts 优雅的解决方案

【讨论】:

  • @RossDrew 这似乎是一个很好的答案,你能告诉我如何在索引 for 循环中完成这一切吗?
  • @Ross 最简单的解决方案将失败,其中列表中 >=2 个连续元素存在于文本文件中。它会失败,因为列表在删除元素后会移动元素,并且我们总是在循环时增加索引。
  • @rishi007bansod 很好发现。更新了我的答案。
【解决方案3】:

我会做的是使用迭代器,然后删除该项目,然后在最后添加它们。

List<String> toAdd = new ArrayList<>();
Iterator iter = listToReorder.iterator();
while(iter.hasNext()){
   String string = iter.next();
   if(checkIfWordIsInTextFile(string)){
       toAdd.add(string);
       iter.next();
   }
}

listToReorder.addAll(toAdd);

【讨论】:

    【解决方案4】:

    如前所述,您可以remove您的字符串在列表中的第一次出现,然后添加它,或者创建一个新列表。但也可以对列表进行排序,以便文本文件中的所有单词最后出现:

    listToReorder.sort((s1, s2) -> {
        if (checkIfWordIsInTextFile(s1))
            return 1;
        return -1;
    });
    

    【讨论】:

    • 喜欢这个。在我稍微更基本的答案中引用了它
    猜你喜欢
    • 2022-01-12
    • 2023-03-03
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 2023-02-09
    • 1970-01-01
    相关资源
    最近更新 更多