我有一个对象列表List<A> list1
...
A
有两个成员id
和name
...现在我还有一个列表List<Integer> list2
只包含了ID。
..我需要从A
中{id}不存在的list1
中移除所有list2
个对象。
到目前为止我尝试过:
void removeUnwanted(List<A> a, List<Integer> b) {
for (A object : a) {
if (!(b.contains(object.id))) {
b.remove(object)
}
}
}
任何人都可以帮我提出最有效的方法吗?
答案 0 :(得分:6)
你应该将id添加到一个集合中以进行快速搜索,然后遍历列表并删除不在id集合中的id:
Set<Integer> ids = new HashSet<Integer>(list2);
Iterator<A> it = list1.iterator();
while (it.hasNext()) {
if (!ids.contains(it.next().id)) {
it.remove();
}
}
答案 1 :(得分:1)
可以在O(n)
时间(平均大小写)和空格中通过创建HashMap<Integer,A>
来完成,其中键是ID,值是A
对象。
现在,迭代列表list2
并仅生成具有与A
中某个ID匹配的键的值(list2
个对象)。
类似java的伪代码:
Map<Integer,A> map = new HashMap<>();
for (A a : list1) map.put(a.id,a);
for (int id : list2) {
A a = map.get(id);
//do something with a, maybe populate a new list
}
另一种方法是对两个列表进行排序,并且并行迭代,同时丢弃没有匹配id的元素。这给出了O(nlogn)时间(最坏情况)和O(1)空间:
高级伪代码:
sort(list1) //according to id
sort(list2)
iter1 = 0
iter2 = 0
while (iter1<list1.size() && iter2<list2.size()) {
int id = list1.get(iter1).id
if (id < list2.get(iter2)) { //discard and advance the smaller one
list1.remove(iter1) //can be done efficiently if the list is linked list
} else if (id == list2.get(iter2)) { //advance both, element should remain in list1
iter1++; iter2++;
} else { //advance iter2
iter2++;
}
}
答案 2 :(得分:1)
使用流(Java8)可以写:
List<Obj> objects = new LinkedList<>();
List<Integer> ids = new LinkedList<>();
// fill objects and ids
Set<Integer> idHash = new HashSet<>(ids);
objects = new LinkedList<>(objects.stream()
.filter(e -> idHash.contains(e.getID()))
.collect(Collectors.toList()));
答案 3 :(得分:0)
public void removeUnwanted(List<A> a, List<Integer> b) {
boolean result = false;
for (A object : a) {
for (int i : b) {
if ((i == (object.id))) {
result = true;
}
}
if (result == false) {
a.remove(object);
}
result = false;
}
}