まず一般的なケース:フラグを使用して、コレクションの特定の要素が特定の条件を満たすかどうかを確認することは珍しくありません。しかし、私がこれを解決するために最も頻繁に見たパターンは、追加のメソッドでチェックを移動し、それから直接戻ることです(彼の答えで説明されているキリアン・フォスのように):
private <T> boolean checkCollection(Collection<T> collection)
{
for (T element : collection)
if (checkElement(element))
return true;
return false;
}
Java 8以降では、以下を使用したより簡潔な方法がありますStream.anyMatch(…)
。
collection.stream().anyMatch(this::checkElement);
あなたの場合、これはおそらく次のようlist == entry.getValue()
になります(あなたの質問を想定しています):
map.values().stream().anyMatch(list -> list.size() > limit);
あなたの特定の例の問題は、への追加の呼び出しfillUpList()
です。答えは、このメソッドの実行内容に大きく依存します。
サイドノート:現状では、への呼び出しfillUpList()
はあまり意味がありません。なぜなら、それは現在反復している要素に依存しないからです。これは、質問の形式に合わせて実際のコードを削除した結果だと思います。しかし、まさにそれは、解釈が難しく、したがって推論するのが難しい人為的な例につながります。したがって、最小限、完全、検証可能な例を提供することが非常に重要です。
したがって、実際のコードentry
はメソッドに電流を渡すと仮定します。
ただし、さらに質問があります。
- このコードに到達する前に、マップ内のリストは空ですか?もしそうなら、なぜ
BigInteger
キーのリストまたはセットだけでなく、すでにマップがあるのですか?それらが空でない場合、なぜリストを埋める必要があるのですか?リストに既に要素がある場合、この場合は更新または他の何らかの計算ではありませんか?
- リストが制限より大きくなる原因は何ですか?これはエラー状態ですか、それとも頻繁に発生すると予想されますか?無効な入力が原因ですか?
- 制限を超えるリストに到達するまで、リストを計算する必要がありますか?
- 「何かをする」部分は何をしますか?
- この部品の後に充填を再開しますか?
これは、コードフラグメントを理解しようとしたときに思いついたいくつかの質問です。だから、私の意見では、それは本当のコードの匂いです:あなたのコードは意図を明確に伝えていません。
これは次のいずれかを意味する場合があります(「すべてまたは何も」および制限に達するとエラーを示します)。
/**
* Computes the list of all foo strings for each passed number.
*
* @param numbers the numbers to process. Must not be {@code null}.
* @return all foo strings for each passed number. Never {@code null}.
* @throws InvalidArgumentException if any number produces a list that is too long.
*/
public Map<BigInteger, List<String>> computeFoos(Set<BigInteger> numbers)
throws InvalidArgumentException
{
if (numbers.isEmpty())
{
// Do you actually need to log this here?
// The caller might know better what to do in this case...
logger.info("Nothing to compute");
}
return numbers.stream().collect(Collectors.toMap(
number -> number,
number -> computeListForNumber(number)));
}
private List<String> computeListForNumber(BigInteger number)
throws InvalidArgumentException
{
// compute the list and throw an exception if the limit is exceeded.
}
または、これが意味する場合があります(「最初の問題まで更新」):
/**
* Refreshes all foo lists after they have become invalid because of bar.
*
* @param map the numbers with all their current values.
* The values in this map will be modified.
* Must not be {@code null}.
* @throws InvalidArgumentException if any new foo list would become too long.
* Some other lists may have already been updated.
*/
public void updateFoos(Map<BigInteger, List<String>> map)
throws InvalidArgumentException
{
map.replaceAll(this::computeUpdatedList);
}
private List<String> computeUpdatedList(
BigInteger number, List<String> currentValues)
throws InvalidArgumentException
{
// compute the new list and throw an exception if the limit is exceeded.
}
または、これ(「すべてのリストを更新するが、元のリストが大きくなりすぎた場合は保持する」):
/**
* Refreshes all foo lists after they have become invalid because of bar.
* Lists that would become too large will not be updated.
*
* @param map the numbers with all their current values.
* The values in this map will be modified.
* Must not be {@code null}.
* @return {@code true} if all updates have been successful,
* {@code false} if one or more elements have been skipped
* because the foo list size limit has been reached.
*/
public boolean updateFoos(Map<BigInteger, List<String>> map)
{
boolean allUpdatesSuccessful = true;
for (Entry<BigInteger, List<String>> entry : map.entrySet())
{
List<String> newList = computeListForNumber(entry.getKey());
if (newList.size() > limit)
allUpdatesSuccessful = false;
else
entry.setValue(newList);
}
return allUpdatesSuccessful;
}
private List<String> computeListForNumber(BigInteger number)
{
// compute the new list
}
または、次の場合でも(computeFoos(…)
最初の例から使用しますが、例外はありません):
/**
* Processes the passed numbers. An optimized algorithm will be used if any number
* produces a foo list of a size that justifies the additional overhead.
*
* @param numbers the numbers to process. Must not be {@code null}.
*/
public void process(Collection<BigInteger> numbers)
{
Map<BigInteger, List<String>> map = computeFoos(numbers);
if (isLimitReached(map))
processLarge(map);
else
processSmall(map);
}
private boolean isLimitReached(Map<BigInteger, List<String>> map)
{
return map.values().stream().anyMatch(list -> list.size() > limit);
}
または、まったく異なるものを意味する可能性があります... ;-)