【问题标题】:Java: How to loop through three List<String>Java:如何遍历三个 List<String>
【发布时间】:2012-09-04 13:47:48
【问题描述】:

我有三个 List&lt;String&gt; 变量:classFilesusernamesfileDirectories。我有一个String(一个字符串列表,但我会将列表中的每个字符串与下面的循环进行比较),它由每个列表中的一个项目组成。我想遍历所有三个列表并检查所有三个列表中的一个值是否在字符串中

最好的方法是什么?

for(String classFile:classFiles) {
//if contains classfile statement
  for(String username:usernames) {
  //if contains username statement
    for(String fileDirectory:fileDirectories) {
      //if contains filedirectory statement
    }
  }
}

for(String classFile:classFiles) {
  for(String username:usernames) {
    for(String fileDirectory:fileDirectories) {
      //if statement
    }
  }
}

for(String classFile:classFiles) {
  //make list of files that contain classFile
}

for(String username:usernames) {
  //remove items from list that do not contain username
}

for(String fileDirectory:fileDirectories){
  //remove items from list that do not contain fileDirectory
}

或者有更好的方法吗?

编辑:示例

classFiles - a1, a2, a3
usernames - noc1, noc2, noc3
fileDirectories - C:/projects/a1/noc1/example.java, C:/projects/a1/ad3/example.java

以及要检查的字符串

String - C:/bin/a1/noc1/example.class

我想要做的是如果fileDirectory和String都包含一个classFile和用户名,然后将它添加到一个列表中

所以在这个例子中C:/bin/a1/noc1/example.class 将被添加到列表中,但C:/bin/a4/fd1/example.class 不会被添加或C:/bin/a3/noc3/example.class 不会被添加

【问题讨论】:

  • 检查的目的是什么?要确定这 3 个元素具体是什么?为问题提供更多背景信息会有所帮助。
  • 请考虑用示例数据重申您的问题。目前尚不清楚您要完成什么。
  • 你在列表上尝试的三种重复操作,它们完全不相关吗?如果是这种情况,那么所有三种方法都将具有相同的性能 (O(n))。
  • 为什么你不想做'if(classFiles.contains(string)) //do sth'?
  • @Santosh 前两个是 O(n^3)。

标签: java loops for-loop foreach


【解决方案1】:

当您执行删除操作时,for-each 循环不是最佳选择。您应该使用 Iterator 和 remove on iterator 以避免并发修改异常。

相反

for(String fileDirectory:fileDirectories){
  //remove items from list that do not contain fileDirectory
}

你应该做类似的事情

Iterator iter = fileDirectores.iterator();
while(iter.hasNext())
{
//Get next
//Do your check 
iter.remove();
}

这会导致三个单独的迭代来完全满足您的要求。

【讨论】:

  • 那么这是我想要做的最好的方式还是最好的方式?
  • 是的,我觉得这是最好/安全的方法。
  • 是的,我使用了迭代器,经过一些工作,我开始使用它......干杯:)
【解决方案2】:

所以我认为你想得到所有三个列表之间的交集? 只需在 List 上使用retainAll 方法即可。

classFiles.retainAll(usernames);
classFiles.retainAll(fileDirectories);

现在classFiles 将只有三个列表之间的交集。

【讨论】:

  • 我不认为这就是他想要的。正如我理解的问题,实际上有第四个列表 - 一个字符串列表,其中该列表的每个元素都有几个子字符串。他想将这些子字符串与 3 个“选项”列表进行比较。
  • 是的,bfishmam 是正确的。我想检查第 4 个列表的每个元素是否包含来自其他 3 个列表中的每个列表的字符串
【解决方案3】:

您是否可以考虑使用 HashSet 或 HashMap 来快速访问您的字符串值(使用 .contains(string))?

它将消除循环。

如果我能很好地理解问题,我会这样做(不确定^^)

【讨论】:

    【解决方案4】:

    有时最好定义您实际尝试编写的函数:

    /**
      * Checks to see if candidate has one string in each of classFiles, usernames and fileDirectories
      */ 
    public boolean hasEssentialComponents(List<String> candidate) {
      //Code here
    }
    

    现在,您的第一个选项具有非常长的最大运行时间 O(n^3)。如果您希望该函数通常会失败,这意味着对于您的三个列表中的每个项目,您正在循环遍历下一个列表。其中大部分是多余的,如果这些列表很长,您将对性能产生巨大影响。

    第二个略有不同,但总运行时间相同。

    第三个显然更好;在这种情况下,一旦您发现列表没有组件并且您永远不会两次检查列表中的组件,您可能会失败。但是,Java 提供了一些sugar 可以使这更容易。

    public boolean hasEssentialComponents(List<String> candidates) {
      //Sanity check the data
      if (candidate.size() != 3) { return false; } //I'm assuming a 'good' candidate has only three items.
    
      valid = true;
      for (String candidate:candidates) {
        if (valid &&  
            ! (   check(this.classFiles, candidate)
               || check(this.usernames, candidate)
               || check(this.fileDirectories, candidate) )
              )) {
          valid = false;
        }
      }
      return valid;
    }
    
    private boolean check(List<String> masterList, String candidate) {
      return masterList.contains(candidate);
    }
    

    现在,我在这里不必要地冗长,以确保梳理出问题的各个部分。请注意,您应该尽可能使用 Java 内置函数;他们优化得很好。不要把你的清单加在一起;您正在花费不必要的时间进行复制。此外,如果您只需要这样做,则只进行一次比较:请注意,如果您知道字符串列表中的元素应该在您的主列表中的哪个位置,则可以做得更好。

    最后,我真的建议你先写一个方法签名。它迫使你思考你真正想要做什么。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-10-26
      • 2018-08-07
      • 2013-08-11
      • 2017-03-15
      • 2013-05-17
      • 2021-05-28
      • 2012-06-16
      • 1970-01-01
      相关资源
      最近更新 更多