如何在Java中join两个列表?

条件:不要修改原来的列表; 只有JDK,没有外部库。 单线或JDK 1.3版本的奖励积分。

有没有比以下更简单的方法:

List<String> newList = new ArrayList<String>(); newList.addAll(listOne); newList.addAll(listTwo); 

在我头顶,我可以缩短一行:

 List<String> newList = new ArrayList<String>(listOne); newList.addAll(listTwo); 

在Java 8中:

 List<String> newList = Stream.concat(listOne.stream(), listTwo.stream()) .collect(Collectors.toList()); 

你可以使用Apache的commons-collections库:

 List<String> newList = ListUtils.union(list1,list2); 

可能不简单,但有趣和丑陋:

 List<String> newList = new ArrayList<String>() { { addAll(listOne); addAll(listTwo); } }; 

不要在生产代码中使用它;;)

你的要求之一是保留原来的名单。 如果您创build了一个新列表并使用addAll() ,则实际上将对列表中对象的引用数量加倍。 这可能会导致内存问题,如果你的名单是非常大的。

如果不需要修改连接结果,则可以使用自定义列表实现来避免这种情况。 自定义实现类不只一行,显然…但使用它是短而甜。

CompositeUnmodifiableList.java:

 public class CompositeUnmodifiableList<E> extends AbstractList<E> { private final List<E> list1; private final List<E> list2; public CompositeUnmodifiableList(List<E> list1, List<E> list2) { this.list1 = list1; this.list2 = list2; } @Override public E get(int index) { if (index < list1.size()) { return list1.get(index); } return list2.get(index-list1.size()); } @Override public int size() { return list1.size() + list2.size(); } } 

用法:

 List<String> newList = new CompositeUnmodifiableList<String>(listOne,listTwo); 

不简单,但不调整开销:

 List<String> newList = new ArrayList<>(listOne.size() + listTwo.size()); newList.addAll(listOne); newList.addAll(listTwo); 

发现这个问题看来连接任意数量的列表,而不是外部库。 所以,也许它会帮助别人:

 com.google.common.collect.Iterables#concat() 

如果你想把相同的逻辑应用于()中的许多不同的集合,那么这很有用。

另一个Java 8单行版本:

 List<String> newList = Stream.of(listOne, listTwo) .flatMap(x -> x.stream()) .collect(Collectors.toList()); 

作为奖励,因为Stream.of()是可变的,所以你可以连接尽可能多的列表。

 List<String> newList = Stream.of(listOne, listTwo, listThree) .flatMap(x -> x.stream()) .collect(Collectors.toList()); 

这很简单,只是一行,但会将listTwo的内容添加到listOne。 你真的需要把内容放在第三个列表中吗?

 Collections.addAll(listOne, listTwo.toArray()); 

稍短一些将是:

 List<String> newList = new ArrayList<String>(listOne); newList.addAll(listTwo); 

这是一个使用两行的java 8解决scheme:

 List<Object> newList = new ArrayList<>(); Stream.of(list1, list2).forEach(newList::addAll); 

请注意,如果不使用此方法

  • newList的来源是未知的,它可能已经与其他线程共享
  • 修改newList的stream是并行stream,对newList访问不同步或线程安全

由于副作用的考虑。

上述两个条件都不适用于上述两个列表的情况,所以这是安全的。

基于这个答案的另一个问题。

稍微简单一点:

 List<String> newList = new ArrayList<String>(listOne); newList.addAll(listTwo); 

如果目标列表是预先声明的,你可以做一个链接。

 (newList = new ArrayList<String>(list1)).addAll(list2); 

build议的解决scheme是针对三个列表,尽pipe它也可以应用于两个列表。 在Java 8中,我们可以使用Stream.of或Stream.concat作为:

 List<String> result1 = Stream.concat(Stream.concat(list1.stream(),list2.stream()),list3.stream()).collect(Collectors.toList()); List<String> result2 = Stream.of(list1,list2,list3).flatMap(Collection::stream).collect(Collectors.toList()); 

Stream.concat将两个stream作为input,并创build一个延迟级联stream,其元素是第一个stream的所有元素,后面是第二个stream的所有元素。 由于我们有三个列表,我们已经使用了这个方法( Stream.concat )两次。

我们也可以写一个实用类(比如说StringUtils),它带有一个方法,它使用任意数量的列表(使用可变参数 ),并返回一个连接列表:

 public static <T> List<T> concatenatedList(List<T>... collections) { return Arrays.stream(collections).flatMap(Collection::stream).collect(Collectors.toList()); } 

那么我们可以使用这个方法:

 List<String> result3 = StringUtils.concatenatedList(list1,list2,list3); 

Java 8中 (另一种方式):

 List<?> newList = Stream.of(list1, list2).flatMap(List::stream).collect(Collectors.toList()); 

另一个使用Java8stream的Java8解决scheme,因为flatMap解决scheme已经发布,这里是一个没有flatMap的解决scheme

 List<E> li = lol.stream().collect(ArrayList::new, List::addAll, List::addAll); 

要么

 List<E> ints = Stream.of(list1, list2).collect(ArrayList::new, List::addAll, List::addAll); 

  List<List<Integer>> lol = Arrays.asList(Arrays.asList(1, 2, 3), Arrays.asList(4, 5, 6)); List<Integer> li = lol.stream().collect(ArrayList::new, List::addAll, List::addAll); System.out.println(lol); System.out.println(li); 

产量

 [[1, 2, 3], [4, 5, 6]] [1, 2, 3, 4, 5, 6] 

我认为最聪明的是:

 /** * @param smallLists * @return one big list containing all elements of the small ones, in the same order. */ public static <E> List<E> concatenate (final List<E> ... smallLists) { final ArrayList<E> bigList = new ArrayList<E>(); for (final List<E> list: smallLists) { bigList.addAll(list); } return bigList; } 

支持通过对象键join的Java 8版本:

 public List<SomeClass> mergeLists(final List<SomeClass> left, final List<SomeClass> right, String primaryKey) { final Map<Object, SomeClass> mergedList = new LinkedHashMap<>(); Stream.concat(left.stream(), right.stream()) .map(someObject -> new Pair<Object, SomeClass>(someObject.getSomeKey(), someObject)) .forEach(pair-> mergedList.put(pair.getKey(), pair.getValue())); return new ArrayList<>(mergedList.values()); } 

你可以用静态导入和辅助类来完成

这个类的生殖能力可能可以提高

 public class Lists { private Lists() { } // can't be instantiated public static List<T> join(List<T>... lists) { List<T> result = new ArrayList<T>(); for(List<T> list : lists) { result.addAll(list); } return results; } } 

那么你可以做像这样的事情

 import static Lists.join; List<T> result = join(list1, list2, list3, list4); 
 public static <T> List<T> merge(List<T>... args) { final List<T> result = new ArrayList<>(); for (List<T> list : args) { result.addAll(list); } return result; } 

使用助手类。

我build议:

 public static <E> Collection<E> addAll(Collection<E> dest, Collection<? extends E>... src) { for(Collection<? extends E> c : src) { dest.addAll(c); } return dest; } public static void main(String[] args) { System.out.println(addAll(new ArrayList<Object>(), Arrays.asList(1,2,3), Arrays.asList("a", "b", "c"))); // does not compile // System.out.println(addAll(new ArrayList<Integer>(), Arrays.asList(1,2,3), Arrays.asList("a", "b", "c"))); System.out.println(addAll(new ArrayList<Integer>(), Arrays.asList(1,2,3), Arrays.asList(4, 5, 6))); } 

我并不是说这很简单,但是你提到了单线的奖金;-)

 Collection mergedList = Collections.list(new sun.misc.CompoundEnumeration(new Enumeration[] { new Vector(list1).elements(), new Vector(list2).elements(), ... })) 

没有办法靠近单线,但我认为这是最简单的:

 List<String> newList = new ArrayList<String>(l1); newList.addAll(l2); for(String w:newList) System.out.printf("%s ", w); 

如果您的列表具有不同的types,并且想要将它们组合到另一个types的列表中,则可以使用streams和java 8。

 public static void main(String[] args) { List<String> list2 = new ArrayList<>(); List<Pair<Integer, String>> list1 = new ArrayList<>(); list2.add("asd"); list2.add("asdaf"); list1.add(new Pair<>(1, "werwe")); list1.add(new Pair<>(2, "tyutyu")); Stream stream = Stream.concat(list1.stream(), list2.stream()); List<Pair<Integer, String>> res = (List<Pair<Integer, String>>) stream .map(item -> { if (item instanceof String) { return new Pair<>(0, item); } else { return new Pair<>(((Pair<Integer, String>)item).getKey(), ((Pair<Integer, String>)item).getValue()); } }) .collect(Collectors.toList()); } 
 List<?> newList = ListUtils.combine(list1, list2); 

哦,你必须执行combine方法:-)

 public class TestApp { /** * @param args */ public static void main(String[] args) { System.out.println("Hi"); Set<List<String>> bcOwnersList = new HashSet<List<String>>(); List<String> bclist = new ArrayList<String>(); List<String> bclist1 = new ArrayList<String>(); List<String> object = new ArrayList<String>(); object.add("BC11"); object.add("C2"); bclist.add("BC1"); bclist.add("BC2"); bclist.add("BC3"); bclist.add("BC4"); bclist.add("BC5"); bcOwnersList.add(bclist); bcOwnersList.add(object); bclist1.add("BC11"); bclist1.add("BC21"); bclist1.add("BC31"); bclist1.add("BC4"); bclist1.add("BC5"); List<String> listList= new ArrayList<String>(); for(List<String> ll : bcOwnersList){ listList = (List<String>) CollectionUtils.union(listList,CollectionUtils.intersection(ll, bclist1)); } /*for(List<String> lists : listList){ test = (List<String>) CollectionUtils.union(test, listList); }*/ for(Object l : listList){ System.out.println(l.toString()); } System.out.println(bclist.contains("BC")); } } 

如果不介绍自己的实用方法,我无法在一般情况下改进双线程,但如果您确实有string列表,并且您愿意假定这些string不包含逗号,则可以拉长这个长整数-衬垫:

 List<String> newList = new ArrayList<String>(Arrays.asList((listOne.toString().subString(1, listOne.length() - 1) + ", " + listTwo.toString().subString(1, listTwo.length() - 1)).split(", "))); 

如果你放弃generics,这应该符合JDK 1.4(尽pipe我没有testing过)。 也不build议用于生产代码;-)