求算法~java 多个 list 取交集

2015-11-13 17:30:28 +08:00
 ray0625

项目中遇到这么一个问题:
现在有 5 个 list ,这 5 个 list 不一定都是有值的,现在要判断哪几个 list 有值,然后从有值的 list 里取交集,自己想了想逻辑,感觉想出来的有点复杂,求大神赋值简单点的算法

10647 次点击
所在节点    问与答
13 条回复
icegreen
2015-11-13 18:06:09 +08:00
1. 先把有值的筛选出来;
2. 遍历每个 list,把元素存到 map 中, {元素:出现次数} , map 的 key 是元素,value 是出现次数,
3. 最后把 value=list 数量的筛选出来;
yuyue007
2015-11-13 18:15:14 +08:00
@icegreen 为什么还要用 map 。。。
yuyue007
2015-11-13 18:18:23 +08:00
public List<String> xxx(final List<String>... input) {
List<String> result = new ArrayList<String>();
if (input == null || input.length == 0) {
return result;
}

for (List<String> item : input) {
if (item.isEmpty()) {
continue;
}

if (result.isEmpty()) {
result.addAll(item);
continue;
}

result.retainAll(item);
}

return result;
}


没测试过,应该没问题。
kaifeii
2015-11-13 18:23:57 +08:00
List<List> listList = new ArrayList<List>(5);
Set tempSet = new HashSet();
Set resultSet = new HashSet();
resultSet.addAll(listList.get(0));
for (int i = 1;i < 5; ++ i){
tempSet.clear();
tempSet.addAll(listList.get(i));
resultSet.retainAll(tempSet);
}

这样吧大概,用 set 作交集、并集和差集运算很不错,可以上网查一下。
icegreen
2015-11-13 18:29:12 +08:00
@yuyue007
哎呀.....我忘了有 retainAll 这个方法了!!!尴尬;

不过你这个好像还有点问题, 如果前两个的交集为空,这时候 result 是空的,循环到第三个 list 时候, 就会把第三个 list 全部添加进 result 了;
hao123yinlong
2015-11-13 20:00:50 +08:00
Java 实现超简单么。。 都不用自己写算法实现

```
/**
* 从 有值的 list 里取交集
* @param lists
* @return
*/
public List<Object> intersection(List<List<Object>> lists) {
if(lists == null || lists.size() == 0){
return null;
}
ArrayList<List<Object>> arrayList = new ArrayList<>(lists);
for (int i = 0; i < arrayList.size(); i++) {
List<Object> list = arrayList.get(i);
// 去除空集合
if (list == null || list.size() == 0) {
arrayList.remove(list);
i-- ;
}
}
if(arrayList.size() == 0){
return null;
}
List<Object> intersection = arrayList.get(0) ;
// 就只有一个非空集合,结果就是他咯
if(arrayList.size() == 1){
return intersection;
}
// 有多个非空集合,直接挨个交集
for (int i = 1; i < arrayList.size()-1; i++) {
intersection.retainAll(arrayList.get(i));
}
return intersection;
}



public void test() {
List<Object> list1 = new ArrayList<Object>();
List<Object> list2 = new ArrayList<Object>();
List<Object> list3 = new ArrayList<Object>();
List<Object> list4 = new ArrayList<Object>();
List<Object> list5 = new ArrayList<Object>();

initList(list1);
initList(list2);
initList(list3, "3", "4", "5");
initList(list4, "3","4");
initList(list5, "8","3", "3","4");

System.out.println(intersection(Arrays.asList(list1,list2,list3,list4,list5)));

}


/**
* 给 List 添加元素
*
* @param list
* @param item
*/
public void initList(List<Object> list, Object... item) {
if (list == null) {
throw new IllegalArgumentException("list can't be empty!");
}
if (item == null || item.length == 0) {
return;
}
list.addAll(Arrays.asList(item));
}

public static void main(String[] args) {
new Test().test();
}

```
chenwj
2015-11-13 20:58:49 +08:00
stream 风格
```
public static List<Element> retainElementList(List<List<Element>> elementLists) {
checkNotNull(elementLists, "elementLists should not be null!");
Optional<List<Element>> result = elementLists.parallelStream().filter(elementList -> elementList != null && ((List) elementList).size() != 0).reduce((a, b) -> {
a.retainAll(b);
return a;
});
return result.orElse(new ArrayList<>());
}
```
zwy
2015-11-13 21:01:38 +08:00
每次看到 JAVA 就心累啊
ruby 下面只要 setA - (setA - setB) 就好了
ray0625
2015-11-16 09:51:15 +08:00
@icegreen @yuyue007 感谢两位,看了一下这个方法应该没问题,如果前两个为空,第三个不为空,就是应该把第三个全部添加进去,再跟后面不为空的做交集
ray0625
2015-11-16 09:52:12 +08:00
@hao123yinlong 明白了,谢谢,写的好详细
ray0625
2015-11-16 09:52:37 +08:00
@chenwj 这个还真没用过,,,不知道咋用
chenwj
2015-11-16 13:34:35 +08:00
@ray0625 就是一个简单的 reduce ,关键字搜 java8 stream reduce
yuyue007
2015-11-17 18:01:21 +08:00
@icegreen 是的,有问题。反正知道是哪个意思就行了,哈哈。需要改一下初始化第一个被比较元素的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/236012

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX