【发布时间】:2016-07-10 13:40:22
【问题描述】:
我有一个简单的文件,其中每行包含两个整数值(一个源整数和一个目标整数)。每条线代表两个值之间的关系。该文件未排序,实际文件包含大约 400 万行。排序后可能是这样的:
sourceId;targetId
1;5
2;3
4;7
7;4
8;7
9;5
我的目标是创建一个新对象,该对象将表示具有唯一标识符的列表中所有唯一相关的整数。这个例子的预期输出应该是以下三个对象:
0, [1, 5, 9]
1, [2, 3]
2, [4, 7, 8]
所以 groupId 0 包含一组关系(1、5 和 9)。
以下是我目前创建这些对象列表的方法。 Relation 对象列表包含内存中的所有行。 GroupedRelation 列表应该是最终结果。
public class GroupedRelationBuilder {
private List<Relation> relations;
private List<GroupedRelation> groupedRelations;
private List<String> ids;
private int frameId;
public void build() {
relations = new ArrayList<>();
relations.add(new Relation(1, 5));
relations.add(new Relation(4, 7));
relations.add(new Relation(8, 7));
relations.add(new Relation(7, 4));
relations.add(new Relation(9, 5));
relations.add(new Relation(2, 3));
// sort
relations.sort(Comparator.comparing(Relation::getSource).thenComparing(Relation::getTarget));
// build the groupedRelations
groupId = 0;
groupedRelations = new ArrayList<>();
for (int i = 0; relations.size() > 0;) {
ids = new ArrayList<>();
int compareSource = relations.get(i).getSource();
int compareTarget = relations.get(i).getTarget();
ids.add(Integer.toString(compareSource));
ids.add(Integer.toString(compareTarget));
relations.remove(i);
for (int j = 0; j < relations.size(); j++) {
int source = relations.get(j).getSource();
int target = relations.get(j).getTarget();
if ((source == compareSource || source == compareTarget) && !ids.contains(Integer.toString(target))) {
ids.add(Integer.toString(target));
relations.remove(j);
continue;
}
if ((target == compareSource || target == compareTarget) && !ids.contains(Integer.toString(source))) {
ids.add(Integer.toString(source));
relations.remove(j);
continue;
}
}
if (relations.size() > 0) {
groupedRelations.add(new GroupedRelation(groupId++, ids));
}
}
}
class GroupedRelation {
private int groupId;
private List<String> relatedIds;
public GroupedRelation(int groupId, List<String> relations) {
this.groupId = groupId;
this.relatedIds = relations;
}
public int getGroupId() {
return groupId;
}
public List<String> getRelatedIds() {
return relatedIds;
}
}
class Relation {
private int source;
private int target;
public Relation(int source, int target) {
this.source = source;
this.target = target;
}
public int getSource() {
return source;
}
public void setSource(int source) {
this.source = source;
}
public int getTarget() {
return target;
}
public void setTarget(int target) {
this.target = target;
}
}
}
当我运行这个小示例程序时,创建 1000 个 GroupedRelation 对象需要 15 秒。创建 100 万个 GroupedRelation 需要 250 分钟。
我正在寻求帮助以优化我的代码,该代码确实得到了我想要的结果,但只是需要很长时间。
是否可以优化迭代,使预期结果相同,但获得预期结果所需的时间显着减少?如果可以,你会怎么做?
【问题讨论】:
-
您可能想看看数据结构/算法的不相交集/联合查找/合并查找类型,请参阅Wikipedia。具有路径压缩的实现具有(几乎)线性复杂性。
-
我会在
O(n)的时间内一次性完成此操作,构建一个要收集的 id 树
标签: java performance list loops