【问题标题】:Removing string from arraylist从数组列表中删除字符串
【发布时间】:2017-09-06 13:27:59
【问题描述】:

如果一个字符串不是以 13 开头,我需要从数组列表中删除它。我已读入数据文件,并且每一行都作为字符串读入 ArrayList。不以13开头的整行需要去掉。下图是读入的数据文件示例:

13 0 150801 00133990 04 04 1 078 2160 999 1 0 1 0 16 04 07 058 0320 061 0127 068 0546 033 0129 048 0586 042 0133 033
13 0 150801 00140480 04 04 1 086 1730 999 1 0 1 0 13 04 06 047 0309 039 0143 032 0772 017 0131 029 0140 037
13 0 150801 00141320 04 04 1 075 1660 999 1 0 1 0 13 03 06 053 0319 036 0132 037 0733 023 0130 026 0134 029
13 0 150801 00144430 01 01 1 071 1570 999 2 0 1 0 04 03 02 040 0567 065
30 0 150801 0015 15 01 0000 0000 0004 0000 0001 0002 0000 0000 0000 0000 0000 0000 0001 0001 0000 0000 0008 0000
30 0 150801 0015 15 02 0000 0000 0005 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
30 0 150801 0015 15 03 0000 0000 0013 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
30 0 150801 0015 15 04 0000 0000 0021 0000 0000 0001 0001 0000 0000 0001 0000 0000 0000 0006 0000 0000 0007 0001
21 0 150801 0015 15 01 0002 0001 0005 0004 0003 0001 0001 0000 0000 0000 000973 002 001 010 0001 0001
21 0 150801 0015 15 02 0000 0000 0000 0001 0001 0002 0000 0001 0000 0000 000000 000 000 000 0001 0001
21 0 150801 0015 15 03 0000 0001 0000 0000 0001 0004 0003 0001 0002 0001 000000 000 000 000 0003 0003
21 0 150801 0015 15 04 0000 0002 0009 0008 0007 0002 0006 0004 0000 0000 001252 000 004 012 0001 0003
70 0 150801 0015 15 01 0004 0000 0012 0001 00001400 00000000 00005956 00000476 000412 000000 000897 000076 000042542 000000000 000068665 000005776
70 0 150801 0015 15 02 0005 0000 0000 0000 00001790 00000000 00000000 00000000 000511 000000 000000 000000 000053047 000000000 000000000 000000000
70 0 150801 0015 15 03 0011 0002 0000 0000 00003648 00000625 00000000 00000000 001240 000231 000000 000000 000144378 000026705 000000000 000000000
70 0 150801 0015 15 04 0021 0001 0015 0001 00007334 00000417 00006991 00000449 002203 000086 001172 000080 000235235 000007396 000092708 000006400
13 0 150801 00151590 04 04 1 078 2240 999 1 0 1 0 16 04 07 064 0318 073 0137 071 0545 083 0137 079 0604 066 0133 067
13 0 150801 00155070 01 01 1 078 1760 999 1 0 1 0 13 04 06 059 0324 054 0135 060 0643 022 0133 028 0127 049
13 0 150801 00160780 01 01 1 080 2230 999 1 0 1 0 16 04 07 057 0374 059 0132 059 0724 064 0138 066 0456 052 0138 063
13 0 150801 00162180 04 04 1 063 1820 999 1 0 1 0 16 04 07 058 0264 082 0113 081 0474 079 0113 080 0501 069 0113 070

这是我写的,但似乎没有删除任何项目:

public class WIMdataReader {
    public static void main(String[] args) throws IOException {

        //Opens the file
        FileInputStream fis = new FileInputStream("DATA1month.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(fis));

        String readLine;

        //Creates an ArrayList to store the data line by line
        //Using an ArrayList, which handles dynamic sizing, whereas an array will require a defined size up front, which may not be known.
        List<String> WIMdataList = new ArrayList<String>();

        //Reads file line by line
        while ((readLine = br.readLine()) != null) {
            WIMdataList.add(readLine);
        }

        //removes items from the arrayList 
        for (int i = 0; i < WIMdataList.size(); i++) {

            if (WIMdataList.get(i).contains("13")) {

            } else {
                WIMdataList.remove(i);
            }
        }
    }
}

【问题讨论】:

  • 如果您要从列表中删除内容并按索引进行迭代,请向后迭代
  • 为什么不用startsWith() 而不是contains()
  • 除了从List 中删除之外,您还可以做的另一件事是创建一个新的List 并只向其中添加有效条目。
  • Java 8 Streams and Filter 在这里会很好。
  • 谢谢大家,向后迭代,它现在可以工作了。感谢所有帮助!

标签: java string arraylist


【解决方案1】:

如果您要从列表中删除内容并按索引进行迭代,向后迭代。否则,您永远不会在刚刚删除的项目之后立即检查该项目,因此即使它符合您的条件,您也不会删除它。

for (int i = WIMdataList.size() - 1; i >= 0; --i) {
  if (!WIMdataList.get(i).contains("13")) {
    WIMdataList.remove(i);
  }
}

请注意,从ArrayList 的中间重复删除是低效的,因为每次都必须移动所有后续元素。您可以通过迭代 forwards、自己移动元素并在末尾截断列表来避免这种情况:

int dst = 0;
for (int src = 0; src < WIMdataList.size(); ++src) {
  if (WIMdataList.get(src).contains("13")) {
    WIMdataList.set(dst++, WIMdataList.get(src));
  }
}
WIMdataList.subList(dst, WIMdataList.size()).clear();

但是使用removeIf会更容易:

WIMdataList.removeIf(s -> !s.contains("13"));

或过滤器,创建一个新列表:

List<String> filtered = WIMdataList.stream().filter(s -> s.contains("13")).collect(Collectors.toList());

或者,当然,首先不要将它们添加到列表中。

【讨论】:

  • 但将其与startsWith 一起使用,而不是contains
  • @f1sh 在 OP 的代码中:“WIMdataList.get(i).contains("13")”。具体标准并不重要。
【解决方案2】:

您可以避免在第一次填写ArrayList 时添加不以13 开头的Strings 添加:

if(readLine.startsWith("13")){
    WIMdataList.add(readLine);
}

在循环文件内容的while内部。


public class WIMdataReader {
    public static void main(String[] args) throws IOException {
        //Opens the file
        FileInputStream fis = new FileInputStream("DATA1month.txt");
        BufferedReader br = new BufferedReader(new InputStreamReader(fis));

        String readLine;

        //Creates an arrayList to store the data line by line
        //Using an ArrayList, which handles dynamic sizing, whereas an array will require a defined size up front, which may not be known.
        List<String> WIMdataList = new ArrayList<String>();

        //Reads file line by line
        while ((readLine = br.readLine()) != null) {
            if (readLine.startsWith("13")) {
                WIMdataList.add(readLine);
            }
        }

        System.out.println(WIMdataList);
    }
}

如果事先检查,就不会重复循环两次。

【讨论】:

    【解决方案3】:

    您可以使用FilesStream 以更短的方式执行此操作:

    Files.lines(Paths.get("data.txt"))
               .filter(line -> line.startsWith("13"))
               .collect(Collectors.toList());
    

    【讨论】:

    • 原始答案收集到一个列表中,所以你可能想在最后使用.collect(Collectors.toList())
    【解决方案4】:

    您应该将 if 语句放在 while 循环中,这样您就不需要再次遍历列表。

    //Reads file line by line
    while ((readLine = br.readLine()) != null) {
        // regex to dertermine if the first "num" is 13
        if (!readLine.matches("^13 .*")) {
            // add to the list if doesn't start with 13
            WIMdataList.add(readLine);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-10-17
      • 2016-04-26
      • 2013-10-27
      • 1970-01-01
      • 2016-04-03
      • 1970-01-01
      • 1970-01-01
      • 2021-06-24
      • 2011-04-20
      相关资源
      最近更新 更多