我最近创建了一个简单的方法,它采用 HashMap 和 LinkedList 作为参数。它遍历 HashMap,找到遵循以下规则的任意两个条目:
- 此条目的键总和必须能被 100 整除
- 键的总和必须小于 1000
- 如果具有相同值的条目出现多次,则应跳过大小写
遵循这些规则的对将被添加到 LinkedList 中。它看起来像这样:
private static void compare2(HashMap<Integer,String> values,List<String>results){
if (values.size()>1) {
for(HashMap.Entry<Integer,String> entry1:values.entrySet()){
for (HashMap.Entry<Integer,String> entry2:values.entrySet()){
if (entry1.getValue().equals(entry2.getValue()))continue;
if ((entry1.getKey() + entry2.getKey())%100 == 0 && (entry1.getKey() + entry2.getKey())<1000){
results.add(entry1.getKey() + "+" + entry2.getKey() + "=" + entry1.getKey() + entry2.getKey());
results.add(entry1.getValue());
results.add(entry2.getValue());
}
}
}
}
}
现在我想创建类似的方法来查找遵循相同规则的 3 个条目。问题是我想重用现有代码,而不是复制/粘贴此代码并进行修改,但我似乎找不到方法来做到这一点。只要结果相同,我不介意是否需要改变方法。
最佳答案
您可以将数字数量设置为参数:N。
您可以继续使用 for 循环,但另一种示例方法可能是使用 lambda 和流重构您的方法,如下所示:
List<List<Map.Entry<Integer, String>>> compareN(HashMap<Integer, String> map, int n) {
return map.entrySet().stream()
.map(entry -> listOfNAccompanyingEntriesThatSatisfyTheConditions(entry, emptyList(), map, n - 1))
.filter(list -> !list.isEmpty())
.collect(toList());
}
其中方法 listOfNAccompanyingEntriesThatSatisfyTheConditions
是递归方法:
private List<Map.Entry<Integer, String>>
listOfNAccompanyingEntriesThatSatisfyTheConditions(Map.Entry<Integer, String> newEntry,
List<Map.Entry<Integer, String>> selectedEntries,
HashMap<Integer, String> originalMap,
int n) {
List<Map.Entry<Integer, String>> newSelectedEntries = join(newEntry, selectedEntries);
if (n == 0) return satisifiesCondition(newSelectedEntries) ? selectedEntries : emptyList();
return originalMap.entrySet().stream()
.filter(entry -> !selectedEntries.contains(entry) && !entry.equals(newEntry))
.map(entry -> listOfNAccompanyingEntriesThatSatisfyTheConditions(entry, newSelectedEntries, originalMap, n - 1))
.flatMap(Collection::stream)
.collect(toList());
}
对于每个n,该方法都会对原始完整列表进行另一次拍摄,以累积可能满足要求的子列表。如果达到数字数量(n==0),则递归停止并验证停止条件:
private static boolean satisifiesCondition(List<Map.Entry<Integer, String>> entries) {
int sum = sumOfTheKeysFrom(entries);
return sum % 100 == 0 && sum < 1000;
}
但是,这种方法实际上是您的实现的精确翻译,并且仍然存在相同的几个问题。例如,如果您运行它
HashMap<Integer, String> map = new HashMap<Integer, String>() {{
put(1, "fred");
put(2, "anja");
put(24, "tom");
put(45, "eddy");
put(22, "lenny");
put(77, "tommy");
put(55, "henry");
put(43, "alfred");
}};
您将产生双重结果,并且相同条目两次都会产生结果,例如:
[1=fred, 22=lenny, 1=fred, 77=tommy] [2=anja, 55=henry, 2=anja, 43=alfred]
但是,通过一些小调整就可以轻松解决这些问题。
如果您不熟悉流、lambda 或递归,我建议您使用命令式方法来实现相同的功能。另请注意,我并不关心示例代码中的性能,因为我认为这个问题是某种练习。
关于java - 重构 Java 代码以使其可重用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46944867/