2

、、およびの3 つのList<String>変数があります。各リストの1つのアイテムで構成される(文字列のリストですが、リスト内のすべての文字列を以下のループと比較します)があります。3 つのリストすべてをループして、3 つすべてのリストの 1 つの値が文字列に含まれているかどうかを確認したいclassFilesusernamesfileDirectoriesString

これについて最善の方法は何ですか?

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.classC:/bin/a3/noc3/example.class、追加されません

4

4 に答える 4

9

削除操作を実行する場合、for-each ループは最良の選択ではありません。同時変更の例外を回避するには、イテレータを使用してイテレータで削除する必要があります。

その代わり

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();
}

これにより、要件を完全に満たすために 3 つの個別の反復が必要になります。

于 2012-09-11T15:21:04.170 に答える
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) が非常に長くなります。関数が一般的に失敗することが予想される場合、それは、3 つのリストの各項目に対して、次のリストをループしていることを意味します。これらのほとんどは冗長であり、これらのリストが長い場合、パフォーマンスに大きな影響を与えます。

2 つ目は微妙に異なりますが、総実行時間は同じです。

3 番目の方が明らかに優れています。この場合、リストにコンポーネントがなく、コンポーネントのリストを 2 回チェックしないことが判明するとすぐに失敗する可能性があります。ただし、Javaには、これを簡単にするシュガーがいくつか用意されています。

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 組み込み関数を使用する必要があることに注意してください。それらは十分に最適化されています。リストを一緒に追加しないでください。コピーに不必要な時間を費やしています。また、それが必要な場合は、各比較を 1 回だけ行います。文字列リストの要素がマスター リストの 1 つでどこにある必要があるかがわかっている場合は、これをさらに改善できます。

最後に、最初にメソッド シグネチャを書き出すことを強くお勧めします。実際に何をしようとしているのかを考えさせられます。

于 2012-09-11T15:35:51.357 に答える
0

HashSet または HashMap を使用して、(.contains(string) を使用して) 文字列値にすばやくアクセスすることを検討できますか?

ループを解消します。

問題をよく理解していれば、このようにします(わかりません^^)

于 2012-09-11T15:35:18.007 に答える
0

では、3 つのリストすべての共通部分を取得したいと思いますか? retainAllリストのメソッドを使用するだけです。

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

classFilesこれで、3 つのリストすべてが交差するだけになります。

于 2012-09-11T15:26:21.937 に答える