Pertama dari kasus umum: Menggunakan bendera untuk memeriksa apakah beberapa elemen koleksi memenuhi kondisi tertentu tidak biasa. Tetapi pola yang paling sering saya lihat untuk menyelesaikan ini adalah dengan memindahkan cek dalam metode tambahan dan langsung kembali darinya (seperti yang dijelaskan oleh Kilian Foth dalam jawabannya ):
private <T> boolean checkCollection(Collection<T> collection)
{
for (T element : collection)
if (checkElement(element))
return true;
return false;
}
Karena Java 8 ada cara yang lebih ringkas menggunakan Stream.anyMatch(…)
:
collection.stream().anyMatch(this::checkElement);
Dalam kasus Anda, ini mungkin akan terlihat seperti ini (dengan asumsi list == entry.getValue()
dalam pertanyaan Anda):
map.values().stream().anyMatch(list -> list.size() > limit);
Masalah dalam contoh spesifik Anda adalah panggilan tambahan untuk fillUpList()
. Jawabannya sangat tergantung pada apa yang seharusnya dilakukan metode ini.
Catatan: Saat berdiri, panggilan untuk fillUpList()
tidak masuk akal, karena tidak bergantung pada elemen yang saat ini Anda gunakan. Saya kira ini adalah konsekuensi dari melucuti kode Anda yang sebenarnya agar sesuai dengan format pertanyaan. Tapi justru itu mengarah pada contoh buatan yang sulit diartikan dan karenanya sulit dipikirkan. Oleh karena itu sangat penting untuk memberikan Minimal, Lengkap , dan diverifikasi contoh .
Jadi saya berasumsi bahwa kode aktual melewati arus entry
ke metode.
Tetapi ada beberapa pertanyaan lagi:
- Apakah daftar di peta kosong sebelum mencapai kode ini? Jika demikian, mengapa sudah ada peta dan bukan hanya daftar atau set
BigInteger
kunci? Jika tidak kosong, mengapa Anda perlu mengisi daftar? Ketika sudah ada elemen dalam daftar, bukankah itu pembaruan atau perhitungan lain dalam kasus ini?
- Apa yang menyebabkan daftar menjadi lebih besar dari batas? Apakah ini kondisi kesalahan atau diharapkan sering terjadi? Apakah itu disebabkan oleh input yang tidak valid?
- Apakah Anda memerlukan daftar yang dihitung hingga Anda mencapai daftar yang lebih besar dari batas?
- Apa yang dilakukan bagian " Lakukan sesuatu "?
- Apakah Anda memulai kembali pengisian setelah bagian ini?
Ini hanya beberapa pertanyaan yang muncul di benak saya ketika saya mencoba memahami fragmen kode. Jadi, menurut saya, itu adalah bau kode asli : Kode Anda tidak secara jelas mengomunikasikan maksudnya.
Ini bisa berarti ini ("semua atau tidak sama sekali" dan mencapai batas mengindikasikan kesalahan):
/**
* 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.
}
Atau itu bisa berarti ini ("perbarui hingga masalah pertama"):
/**
* 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.
}
Atau ini ("perbarui semua daftar tetapi simpan daftar asli jika terlalu besar"):
/**
* 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
}
Atau bahkan yang berikut (menggunakan computeFoos(…)
dari contoh pertama tetapi tanpa pengecualian):
/**
* 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);
}
Atau itu bisa berarti sesuatu yang sama sekali berbeda ... ;-)