我有三个List<String>
个变量:classFiles
,usernames
和fileDirectories
。我有一个String
(一个字符串列表,但我将比较列表中的每个字符串和下面的循环),它包含每个列表中的一个项目。我想遍历所有三个列表并检查所有三个列表中的一个值是否在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和username,那么将它添加到列表中
因此,在此示例中,C:/bin/a1/noc1/example.class
将添加到列表中,但C:/bin/a4/fd1/example.class
将不会或C:/bin/a3/noc3/example.class
将不会添加
答案 0 :(得分:9)
执行删除操作时,每个循环都不是最佳选择。您应该使用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();
}
这导致有三个单独的迭代来完全满足您的要求。
答案 1 :(得分:1)
有时最好定义您实际尝试编写的功能:
/**
* 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内置函数;他们很好地优化了。不要将您的列表添加到一起;你花了不必要的时间复制。此外,如果您需要的话,只进行一次比较:请注意,如果您知道字符串列表中的元素应该位于您的某个主列表中,那么可以做得更好。
最后,我真的建议你先写一个方法签名。它迫使你去思考你实际上要做的事情。
答案 2 :(得分:0)
所以我认为你想要获得所有三个列表之间的交集?
只需使用List上的retainAll
方法。
classFiles.retainAll(usernames);
classFiles.retainAll(fileDirectories);
现在classFiles
将只有三个列表之间的交集。
答案 3 :(得分:0)
您是否可以考虑使用HashSet或HashMap快速访问您的字符串值(使用.contains(string))?
它将消除循环。
如果我理解这个问题(不确定^^),我会这样做