Java中ArrayLists的交集和联合
有什么方法可以这样做吗? 我正在寻找,但找不到任何。
另一个问题:我需要这些方法,所以我可以过滤文件。 一些是AND
过滤器,一些是OR
过滤器(就像在集合论中),所以我需要根据所有文件和保存这些文件的联合/相交ArrayLists进行过滤。
我应该使用不同的数据结构来保存文件吗? 还有什么可以提供更好的运行时间吗?
这是一个简单的实现,不使用任何第三方库。 优于retainAll
, removeAll
和addAll
主要优点是这些方法不会修改输入到方法的原始列表。
public class Test { public static void main(String... args) throws Exception { List<String> list1 = new ArrayList<String>(Arrays.asList("A", "B", "C")); List<String> list2 = new ArrayList<String>(Arrays.asList("B", "C", "D", "E", "F")); System.out.println(new Test().intersection(list1, list2)); System.out.println(new Test().union(list1, list2)); } public <T> List<T> union(List<T> list1, List<T> list2) { Set<T> set = new HashSet<T>(); set.addAll(list1); set.addAll(list2); return new ArrayList<T>(set); } public <T> List<T> intersection(List<T> list1, List<T> list2) { List<T> list = new ArrayList<T>(); for (T t : list1) { if(list2.contains(t)) { list.add(t); } } return list; } }
集合 (所以ArrayList也)有:
col.retainAll(otherCol) // for intersection col.addAll(otherCol) // for union
如果您接受重复,则使用List实现;如果您不接受,则使用Set实现:
Collection<String> col1 = new ArrayList<String>(); // {a, b, c} // Collection<String> col1 = new TreeSet<String>(); col1.add("a"); col1.add("b"); col1.add("c"); Collection<String> col2 = new ArrayList<String>(); // {b, c, d, e} // Collection<String> col2 = new TreeSet<String>(); col2.add("b"); col2.add("c"); col2.add("d"); col2.add("e"); col1.addAll(col2); System.out.println(col1); //output for ArrayList: [a, b, c, b, c, d, e] //output for TreeSet: [a, b, c, d, e]
这篇文章相当老,但它是第一个在谷歌找到这个话题时弹出。
我想给一个使用Java 8流的更新(基本上)在一行中做同样的事情:
List<T> intersect = list1.stream().filter(list2::contains).collect(Collectors.toList()); List<T> union = Stream.concat(list1.stream(), list2.stream()).distinct().collect(Collectors.toList());
如果有人有一个更好/更快的解决方案,让我知道,但这个解决方案是一个很好的一个班轮,可以很容易地包括在一个方法中,而无需添加不必要的辅助类/方法,仍然保持可读性。
list1.retainAll(list2) - is intersection
工会将removeAll
,然后addAll
。
在集合的文档中查找更多(ArrayList是一个集合) http://download.oracle.com/javase/1.5.0/docs/api/java/util/Collection.html
联盟和交叉点仅限于集合而非列表。 正如你所提到的。
检查过滤器的番石榴库。 番石榴也提供真正的十字路口和工会
static <E> Sets.SetView<E >union(Set<? extends E> set1, Set<? extends E> set2) static <E> Sets.SetView<E> intersection(Set<E> set1, Set<?> set2)
你可以使用Apache公用的 CollectionUtils
。
标记的解决方案效率不高。 它有一个O(n ^ 2)时间复杂度。 我们可以做的是对两个列表进行排序,并执行下面的交集算法。
private static ArrayList<Integer> interesect(ArrayList<Integer> f, ArrayList<Integer> s) { ArrayList<Integer> res = new ArrayList<Integer>(); int i = 0, j = 0; while (i != f.size() && j != s.size()) { if (f.get(i) < s.get(j)) { i ++; } else if (f.get(i) > s.get(j)) { j ++; } else { res.add(f.get(i)); i ++; j ++; } } return res; }
这个在O(n log n)中具有O(n log n + n)的复杂度。 工会以类似的方式完成。 只要确保你对if-elseif-else语句进行了适当的修改即可。
你也可以使用迭代器,如果你想(我知道他们更有效的C + +,我不知道这是否在Java中也是如此)。
我想你应该使用Set
来保存这些文件,如果你想在它们上面进行交集和联合。 然后你可以使用Guava的Sets类来完成一个Predicate
union
, intersection
和过滤。 这些方法和其他建议之间的区别在于,所有这些方法都会创建两个集合的交集,交集等的惰性视图 。 Apache Commons创建一个新的集合并将数据复制到它。 retainAll
通过从中删除元素来更改其中一个集合。
下面是一个如何与流进行交集的方法(记住,您必须使用java 8来处理流):
List<foo> fooList1 = new ArrayList<>(Arrays.asList(new foo(), new foo())); List<foo> fooList2 = new ArrayList<>(Arrays.asList(new foo(), new foo())); fooList1.stream().filter(f -> fooList2.contains(f)).collect(Collectors.toList());
不同类型的列表的一个例子。 如果你在foo和bar之间有一个真实的话,你可以从foo得到一个bar-object而不是你可以修改你的流:
List<foo> fooList = new ArrayList<>(Arrays.asList(new foo(), new foo())); List<bar> barList = new ArrayList<>(Arrays.asList(new bar(), new bar())); fooList.stream().filter(f -> barList.contains(f.getBar()).collect(Collectors.toList());
- retainAll会修改你的列表
- 番石榴没有列表的API(仅用于设置)
我发现ListUtils对于这个用例非常有用。
如果您不想修改现有列表,请使用org.apache.commons.collections中的ListUtils。
ListUtils.intersection(list1, list2)
我也在研究类似的情况,并在这里寻求帮助。 结束了为阵列找到我自己的解决方案。 ArrayList AbsentDates = new ArrayList(); //将存储Array1-Array2
注意:如果可以帮助某人到达此页寻求帮助, 请发布此信息。
ArrayList<String> AbsentDates = new ArrayList<String>();//This Array will store difference public void AbsentDays() { findDates("April", "2017");//Array one with dates in Month April 2017 findPresentDays();//Array two carrying some dates which are subset of Dates in Month April 2017 for (int i = 0; i < Dates.size(); i++) { for (int j = 0; j < PresentDates.size(); j++) { if (Dates.get(i).equals(PresentDates.get(j))) { Dates.remove(i); } } AbsentDates = Dates; } System.out.println(AbsentDates ); }
如果列表中的对象是可散列的(即有一个体面的hashCode和等于函数),表之间最快的方法约。 大小> 20是为两个列表中较大的一个构建一个HashSet。
public static <T> ArrayList<T> intersection(Collection<T> a, Collection<T> b) { if (b.size() > a.size()) { return intersection(b, a); } else { if (b.size() > 20 && !(a instanceof HashSet)) { a = new HashSet(a); } ArrayList<T> result = new ArrayList(); for (T objb : b) { if (a.contains(objb)) { result.add(objb); } } return result; } }
首先,我将数组的所有值复制到一个数组中,然后将重复值删除到数组中。 第12行,解释是否同一个数字出现超过时间,然后把一些额外的垃圾值放入“j”位置。 最后,从开始遍历并检查是否出现相同的垃圾值然后丢弃。
public class Union { public static void main(String[] args){ int arr1[]={1,3,3,2,4,2,3,3,5,2,1,99}; int arr2[]={1,3,2,1,3,2,4,6,3,4}; int arr3[]=new int[arr1.length+arr2.length]; for(int i=0;i<arr1.length;i++) arr3[i]=arr1[i]; for(int i=0;i<arr2.length;i++) arr3[arr1.length+i]=arr2[i]; System.out.println(Arrays.toString(arr3)); for(int i=0;i<arr3.length;i++) { for(int j=i+1;j<arr3.length;j++) { if(arr3[i]==arr3[j]) arr3[j]=99999999; //line 12 } } for(int i=0;i<arr3.length;i++) { if(arr3[i]!=99999999) System.out.print(arr3[i]+" "); } } }
在Java 8中,我使用了如下简单的辅助方法:
public static <T> Collection<T> getIntersection(Collection<T> coll1, Collection<T> coll2){ return Stream.concat(coll1.stream(), coll2.stream()) .filter(coll1::contains) .filter(coll2::contains) .collect(Collectors.toSet()); } public static <T> Collection<T> getMinus(Collection<T> coll1, Collection<T> coll2){ return coll1.stream().filter(not(coll2::contains)).collect(Collectors.toSet()); }
如果你有你的数据集,你可以使用番石榴的Sets
类。
如果数字匹配比我检查它是第一次发生或没有“indexOf()”的帮助,如果数字匹配第一次然后打印并保存到一个字符串,以便当下一次相同的数字匹配,然后赢得'因为“indexOf()”条件将是错误的。
class Intersection { public static void main(String[] args) { String s=""; int[] array1 = {1, 2, 5, 5, 8, 9, 7,2,3512451,4,4,5 ,10}; int[] array2 = {1, 0, 6, 15, 6, 5,4, 1,7, 0,5,4,5,2,3,8,5,3512451}; for (int i = 0; i < array1.length; i++) { for (int j = 0; j < array2.length; j++) { char c=(char)(array1[i]); if(array1[i] == (array2[j])&&s.indexOf(c)==-1) { System.out.println("Common element is : "+(array1[i])); s+=c; } } } }
}