Trước hết là trường hợp chung: Sử dụng cờ để kiểm tra xem một số phần tử của bộ sưu tập có đáp ứng một điều kiện nhất định không phải là hiếm. Nhưng mô hình mà tôi đã thấy thường xuyên nhất để giải quyết điều này là chuyển séc theo một phương thức bổ sung và trực tiếp trở về từ nó (như Kilian Foth được mô tả trong câu trả lời của anh ấy ):
private <T> boolean checkCollection(Collection<T> collection)
{
for (T element : collection)
if (checkElement(element))
return true;
return false;
}
Vì Java 8 có một cách ngắn gọn hơn bằng cách sử dụng Stream.anyMatch(…)
:
collection.stream().anyMatch(this::checkElement);
Trong trường hợp của bạn, điều này có thể sẽ trông như thế này (giả sử list == entry.getValue()
trong câu hỏi của bạn):
map.values().stream().anyMatch(list -> list.size() > limit);
Vấn đề trong ví dụ cụ thể của bạn là cuộc gọi bổ sung fillUpList()
. Câu trả lời phụ thuộc rất nhiều vào những gì phương pháp này được cho là làm.
Lưu ý bên lề: Vì nó đứng, cuộc gọi đến fillUpList()
không có nhiều ý nghĩa, bởi vì nó không phụ thuộc vào yếu tố bạn hiện đang lặp lại. Tôi đoán đây là hậu quả của việc tước mã thực tế của bạn để phù hợp với định dạng câu hỏi. Nhưng chính xác điều đó dẫn đến một ví dụ nhân tạo khó diễn giải và do đó khó lý luận. Do đó, điều rất quan trọng là cung cấp một ví dụ Tối thiểu, Hoàn chỉnh và Có thể kiểm chứng .
Vì vậy, tôi giả sử rằng mã thực tế truyền hiện tại entry
cho phương thức.
Nhưng có nhiều câu hỏi hơn để hỏi:
- Các danh sách trong bản đồ có trống không trước khi đạt được mã này? Nếu vậy, tại sao đã có bản đồ và không chỉ là danh sách hoặc bộ
BigInteger
chìa khóa? Nếu chúng không trống, tại sao bạn cần điền vào danh sách? Khi đã có các yếu tố trong danh sách, đó không phải là một bản cập nhật hoặc một số tính toán khác trong trường hợp này?
- Điều gì khiến một danh sách trở nên lớn hơn giới hạn? Đây có phải là một điều kiện lỗi hoặc dự kiến sẽ xảy ra thường xuyên? Có phải do đầu vào không hợp lệ?
- Bạn có cần các danh sách được tính đến điểm bạn đạt đến một danh sách lớn hơn giới hạn không?
- Phần " Làm gì đó " làm gì?
- Bạn có khởi động lại điền sau phần này?
Đây chỉ là một số câu hỏi xuất hiện trong đầu tôi khi tôi cố gắng hiểu đoạn mã. Vì vậy, theo tôi, đó là mùi mã thực sự : Mã của bạn không truyền đạt rõ ràng ý định.
Nó có thể có nghĩa này ("tất cả hoặc không có gì" và đạt đến giới hạn cho thấy có lỗi):
/**
* 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.
}
Hoặc nó có thể có nghĩa này ("cập nhật cho đến khi vấn đề đầu tiên"):
/**
* 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.
}
Hoặc cái này ("cập nhật tất cả các danh sách nhưng giữ danh sách gốc nếu nó quá lớn"):
/**
* 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
}
Hoặc thậm chí sau đây (sử dụng computeFoos(…)
từ ví dụ đầu tiên nhưng không có ngoại lệ):
/**
* 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);
}
Hoặc nó có thể có nghĩa là một cái gì đó hoàn toàn khác nhau ;-)