我有一个Object1(List<Object1>
)列表和一个Object2列表(List<Object2>
)
id
object1id
我有一些SQL背景,我尝试做的是执行&#34;左连接&#34;上
object1.id = object2.object1id
这将导致代表左连接的List<Object3>
。
我可以用Java硬编码算法(for ... for ...),但我确信这对于至少n * m的复杂度来说不会有效。
你有更好的解决方案吗? (如果可能,请附上代码,谢谢!)
答案 0 :(得分:7)
你正在尝试做一些Java并不是真正意义上的事情。
如果你能够做到这一点,你最好将属性添加到Object1
,这将是包含与{相关的对象的Object2
的列表。 {1}}。
如果你不能,我们仍然可以选择天真地做,否则你可以尝试这样的事情:
this
不完美,因为你必须将所有id存储在HashSet中,但由于在HashSet中添加和访问元素是O(1)(理论上),算法是O(n + m)
如果您的HashSet<Integer> hs = new HashSet<Integer>(list2.size());
for(Object2 o : list2) {
hs.add(o.object1id);
}
//hs contains all the ids of list2
List<Object1> result = new ArrayList<Object1>(); //Or another class implementing List
for(Object1 o : list1) {
if(hs.contains(o.id))
result.add(o);
}
课程是使用Object3
和Object1
构建的,请使用Object2
代替HasMap
,其中键为ID,值为对象2。代码中的最后一个HashSet
循环将变为:
for
进一步对ÓscarLópez发表评论:
如果你的目标是不唯一的,你必须按如下方式调整代码:
Object2 o2 = hs.get(o.id);
if(o2 != null)
result.add(new Object3(o, o2);
仍然在O(n + m),但有更大的常数...
答案 1 :(得分:2)
在List上创建索引。扫描列表并填写索引:
HashMap<Integer, Object2> index=HashMap<Integer, Object2>();
for (Object2 obj2: list2) {
index.put(obj2.object1id, obj2);
}
然后,扫描列表并进行连接:
for (Object1 obj1: list1) {
Object2 obj2=index.get(obj1.id); // may be null
Object3 obj3=new Object3(obj1, obj2);
}
答案 2 :(得分:1)
如果您使用的是Java 8,则可以使用streams。它可能看起来像这样(假设id
是要查找的Object1的id):
List<Object3> newList = obj2List.stream().filter(x -> x.object1id == id).map(x -> obj2To3(x)).collect(Collectors.toList());
提供的案例非常模糊,因此很难给出更详细的答案。
答案 3 :(得分:1)
我认为O(n*m)
解决方案是不可避免的,除非创建更复杂的数据结构基础结构 - 数据库中的高效连接是implemented使用索引,哈希等。另外请记住,正确的实现应考虑list2
中的多个对象具有相同object1id
的情况 - 我的代码在这种情况下有效,但所有解决方案只添加{{1} } obj2.object1id
或Set
中的键会失败。
但实施复杂性值得吗?如果输入列表很小,Map
解决方案就可以正常工作。这是我的建议,使用好的旧嵌套循环:
O(n*m)
为了实现上述目的,我使用的输出对象如下所示:
List<Object3> list3 = new ArrayList<>();
for (Object1 obj1 : list1) {
boolean found = false;
for (Object2 obj2 : list2) {
if (obj1.id.equals(obj2.object1id)) {
list3.add(new Object3(obj1, obj2));
found = true;
}
}
if (!found)
list3.add(new Object3(obj1, null));
}
答案 4 :(得分:1)
一个好的解决方案可能是将Object2的List转换为Map。然后遍历Object1 List并从Map获取Object2,最终创建Join并在Object3 List中添加结果。
答案 5 :(得分:0)
如果它们实现了一些通用接口(这会使事情变得更容易,特别是使用转换),那么这是相对简单的。
它仍然是O(nm),因为您必须遍历列表的两个长度才能找到要添加的元素。
public interface JoinInterface {
int getId();
int getObject1Id(); // likely baggage here
}
public static List<? extends JoinableEntity> leftJoin(List<? extends JoinableEntity> left,
List<? extends JoinableEntity> right) {
List<JoinableEntity> result = new ArrayList<>();
result.addAll(left);
for(JoinableEntity aLeft : left) {
for(JoinableEntity aRight : right) {
if(aLeft.getId() == aRight.getObject1Id()) {
result.add(aRight);
break;
}
}
}
return result;
}