【发布时间】:2022-01-02 04:24:09
【问题描述】:
如何将集合中的所有对象与同一集合中的所有其他对象进行比较?我目前将 for 循环与另一个嵌套的 for 循环一起使用。但是,这很慢,我想优化我的方法。
请参阅下面的示例。具体来说,如何优化personsGroupedByFirstName 方法?该方法检索Person 的列表并将其转换为地图,其中每个Person 与具有相同firstName 的其他人分组。
谢谢。
import java.util.*;
class Scratch {
public static void main(String[] args) {
new Scratch().start();
}
public void start() {
List<Person> persons = getPersons();
Map<String, List<Person>> stacks = personsGroupedByFirstName(persons);
for (Map.Entry<String, List<Person>> entrySet : stacks.entrySet()) {
String key = entrySet.getKey();
List<Person> value = entrySet.getValue();
System.out.println("First name: " + key);
System.out.println("People: " + value);
}
}
private List<Person> getPersons() {
return List.of(
new Person("Andrew", "Red"), new Person("Bob", "Red"),
new Person("Craig", "Red"), new Person("Daniel", "Red"),
new Person("Andrew", "Yellow"), new Person("Bob", "Yellow"),
new Person("Craig", "Yellow"), new Person("Daniel", "Yellow"),
new Person("Andrew", "Pink"), new Person("Bob", "Pink"),
new Person("Craig", "Pink"), new Person("Daniel", "Pink"),
new Person("Andrew", "Green"), new Person("Bob", "Green"),
new Person("Craig", "Green"), new Person("Daniel", "Green"),
new Person("Andrew", "Orange"), new Person("Bob", "Orange"),
new Person("Craig", "Orange"), new Person("Daniel", "Orange"),
new Person("Andrew", "Purple"), new Person("Bob", "Purple"),
new Person("Craig", "Purple"), new Person("Daniel", "Purple"),
new Person("Andrew", "Blue"), new Person("Bob", "Blue"),
new Person("Craig", "Blue"), new Person("Daniel", "Blue")
);
}
private Map<String, List<Person>> personsGroupedByFirstName(List<Person> persons) {
Map<String, List<Person>> stacks = new HashMap<>();
int loop = 0;
for (Person outer : persons) {
if (!outer.isReachable()) {
continue;
}
String outerFirstName = outer.getFirstName();
List<Person> stack = new ArrayList<>();
for (Person inner : persons) {
loop = loop + 1;
if (!inner.isReachable()) {
continue;
}
if (isSimilar(outerFirstName, inner.getFirstName())) {
inner.setReachable(false);
stack.add(inner);
}
}
List<Person> tmp = stacks.get(outerFirstName);
if (tmp == null) {
tmp = new ArrayList<>();
}
tmp.addAll(stack);
stacks.put(outerFirstName, tmp);
}
System.out.println("Total Loops: " + loop);
return stacks;
}
/*
* Trivial condition. My actual use case computes the Levenshtein Distance.
* */
private boolean isSimilar(String outerFirstName, String outerSecondName) {
return outerFirstName.equals(outerSecondName);
}
}
class Person {
private final String firstName;
private final String secondName;
private boolean reachable = true;
public Person(String firstName, String secondName) {
this.firstName = firstName;
this.secondName = secondName;
}
public String getFirstName() {
return firstName;
}
public String getSecondName() {
return secondName;
}
public boolean isReachable() {
return reachable;
}
public void setReachable(boolean reachable) {
this.reachable = reachable;
}
@Override
public String toString() {
return "Person{" +
"firstName='" + firstName + '\'' +
", secondName='" + secondName + '\'' +
'}';
}
}
【问题讨论】:
-
您可以进行的一项优化:您的内部循环不需要遍历列表中的所有元素。只是在外循环中的那个之后。如果您的外部循环根据 2、3、4... 等检查元素 1,那么当您的外部循环检查元素 2 时,您已经将其与上一次迭代中的元素 1 进行了比较。所以没有必要再做一次。当然,与自己相比是毫无意义的。因此,没有必要从头开始内部循环,只有元素 3 中的所有内容才是您关心的内容
-
isReachable()属性是什么?查询修改了它正在处理的对象,这看起来很奇怪。
标签: java performance collections comparison