条件:不要修改原始列表;仅限JDK,没有外部库。单行或JDK 1.3版本的奖励积分。
是否有比以下更简单的方法:
List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);
答案 0 :(得分:507)
离开我的头顶,我可以将它缩短一行:
List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
答案 1 :(得分:467)
在Java 8中:
List<String> newList = Stream.concat(listOne.stream(), listTwo.stream())
.collect(Collectors.toList());
答案 2 :(得分:256)
您可以使用Apache commons-collections库:
List<String> newList = ListUtils.union(list1, list2);
答案 3 :(得分:80)
您的一个要求是保留原始列表。如果您创建新列表并使用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);
答案 4 :(得分:79)
可能不简单,但有趣和丑陋:
List<String> newList = new ArrayList<String>() { { addAll(listOne); addAll(listTwo); } };
请勿在生产代码中使用它;;)
答案 5 :(得分:64)
不简单,但没有调整开销:
List<String> newList = new ArrayList<>(listOne.size() + listTwo.size());
newList.addAll(listOne);
newList.addAll(listTwo);
答案 6 :(得分:54)
另一个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());
答案 7 :(得分:50)
发现这个问题想要连接任意数量的列表,而不是关注外部库。所以,也许它会帮助别人:
com.google.common.collect.Iterables#concat()
如果您想将相同的逻辑应用于()中的一个不同集合,则非常有用。
答案 8 :(得分:35)
这是一个使用两行的java 8解决方案:
List<Object> newList = new ArrayList<>();
Stream.of(list1, list2).forEach(newList::addAll);
请注意,如果
,则不应使用此方法newList
的来源未知且可能已与其他线程共享newList
的流是并行流,对newList
的访问不同步或线程安全由于副作用的考虑。
上述两个条件都不适用于上述加入两个列表的情况,因此这是安全的。
基于this answer另一个问题。
答案 9 :(得分:30)
这很简单,只有一行,但会将listTwo的内容添加到listOne中。你真的需要将内容放在第三个列表中吗?
Collections.addAll(listOne, listTwo.toArray());
答案 10 :(得分:25)
建议的解决方案适用于三个列表,尽管它也可以应用于两个列表。在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.concat
)。
我们还可以编写一个实用程序类,其方法可以使用任意数量的列表(使用varargs)并返回一个连接列表:
public static <T> List<T> concatenateLists(List<T>... collections) {
return Arrays.stream(collections).flatMap(Collection::stream).collect(Collectors.toList());
}
然后我们可以将此方法用作:
List<String> result3 = Utils.concatenateLists(list1,list2,list3);
答案 11 :(得分:24)
稍微简单一些:
List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
答案 12 :(得分:20)
稍短一点就是:
List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
答案 13 :(得分:13)
如果目标列表是预先声明的,您可以进行一次划线。
(newList = new ArrayList<String>(list1)).addAll(list2);
答案 14 :(得分:9)
您可以创建通用 Java 8 实用程序方法来连接任意数量的列表。
@SafeVarargs
public static <T> List<T> concat(List<T>... lists) {
return Stream.of(lists).flatMap(List::stream).collect(Collectors.toList());
}
答案 15 :(得分:8)
使用Java8
流的另一个线性解决方案,因为flatMap
解决方案已经发布,这里是一个没有flatMap
的解决方案
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]
答案 16 :(得分:7)
在 Java 8 (另一种方式)中:
List<?> newList =
Stream.of(list1, list2).flatMap(List::stream).collect(Collectors.toList());
答案 17 :(得分:6)
几乎所有的答案都建议使用ArrayList。
List<String> newList = new LinkedList<>(listOne);
newList.addAll(listTwo);
首选使用LinkedList进行有效的添加操作。
ArrayList add被O(1)摊销,但是O(n)在最坏的情况下,因为必须调整数组的大小并复制它。 而LinkedList的添加始终为常数O(1)。
答案 18 :(得分: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;
}
答案 19 :(得分:5)
您可以使用静态导入和帮助程序类
来完成此操作nb 这个类的泛化可能会得到改善
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);
答案 20 :(得分:5)
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());
}
答案 21 :(得分:4)
我们可以使用java8和2种方法来加入2个列表。
List<String> list1 = Arrays.asList("S", "T");
List<String> list2 = Arrays.asList("U", "V");
1)使用concat:
List<String> collect2 = Stream.concat(list1.stream(), list2.stream()).collect(toList());
System.out.println("collect2 = " + collect2); // collect2 = [S, T, U, V]
2)使用flatMap:
List<String> collect3 = Stream.of(list1, list2).flatMap(Collection::stream).collect(toList());
System.out.println("collect3 = " + collect3); // collect3 = [S, T, U, V]
答案 22 :(得分:3)
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;
}
答案 23 :(得分:3)
使用助手类。
我建议:
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)));
}
答案 24 :(得分:1)
public static <T> List<T> merge(@Nonnull final List<T>... list) {
// calculate length first
int mergedLength = 0;
for (List<T> ts : list) {
mergedLength += ts.size();
}
final List<T> mergedList = new ArrayList<>(mergedLength);
for (List<T> ts : list) {
mergedList.addAll(ts);
}
return mergedList;
}
答案 25 :(得分:0)
如果您的列表有不同的类型,并且您希望将它们组合到另一种类型的列表中,那么这是使用流和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());
}
答案 26 :(得分:0)
我并不是说这很简单,但你提到了单线奖金; - )
Collection mergedList = Collections.list(new sun.misc.CompoundEnumeration(new Enumeration[] {
new Vector(list1).elements(),
new Vector(list2).elements(),
...
}))
答案 27 :(得分:0)
如果您想静态地执行此操作,可以执行以下操作。
示例以自然顺序(== Enum-order)A, B
使用2个EnumSet,然后在ALL
列表中加入。
public static final EnumSet<MyType> CATEGORY_A = EnumSet.of(A_1, A_2);
public static final EnumSet<MyType> CATEGORY_B = EnumSet.of(B_1, B_2, B_3);
public static final List<MyType> ALL =
Collections.unmodifiableList(
new ArrayList<MyType>(CATEGORY_A.size() + CATEGORY_B.size())
{{
addAll(CATEGORY_A);
addAll(CATEGORY_B);
}}
);
答案 28 :(得分:0)
靠近单行,但我认为这是最简单的:
List<String> newList = new ArrayList<String>(l1);
newList.addAll(l2);
for(String w:newList)
System.out.printf("%s ", w);
答案 29 :(得分:0)
import java.util.AbstractList;
import java.util.List;
/**
* The {@code ConcatList} is a lightweight view of two {@code List}s.
* <p>
* This implementation is <em>not</em> thread-safe even though the underlying lists can be.
*
* @param <E>
* the type of elements in this list
*/
public class ConcatList<E> extends AbstractList<E> {
/** The first underlying list. */
private final List<E> list1;
/** The second underlying list. */
private final List<E> list2;
/**
* Constructs a new {@code ConcatList} from the given two lists.
*
* @param list1
* the first list
* @param list2
* the second list
*/
public ConcatList(final List<E> list1, final List<E> list2) {
this.list1 = list1;
this.list2 = list2;
}
@Override
public E get(final int index) {
return getList(index).get(getListIndex(index));
}
@Override
public E set(final int index, final E element) {
return getList(index).set(getListIndex(index), element);
}
@Override
public void add(final int index, final E element) {
getList(index).add(getListIndex(index), element);
}
@Override
public E remove(final int index) {
return getList(index).remove(getListIndex(index));
}
@Override
public int size() {
return list1.size() + list2.size();
}
@Override
public boolean contains(final Object o) {
return list1.contains(o) || list2.contains(o);
}
@Override
public void clear() {
list1.clear();
list2.clear();
}
/**
* Returns the index within the corresponding list related to the given index.
*
* @param index
* the index in this list
*
* @return the index of the underlying list
*/
private int getListIndex(final int index) {
final int size1 = list1.size();
return index >= size1 ? index - size1 : index;
}
/**
* Returns the list that corresponds to the given index.
*
* @param index
* the index in this list
*
* @return the underlying list that corresponds to that index
*/
private List<E> getList(final int index) {
return index >= list1.size() ? list2 : list1;
}
}
答案 30 :(得分:-5)
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"));
}
}
答案 31 :(得分:-5)
在没有引入自己的实用程序方法的情况下,我无法在一般情况下改进双线程,但如果你有字符串列表并且你愿意假设这些字符串不包含逗号,你可以拉这个漫长的单行:
List<String> newList = new ArrayList<String>(Arrays.asList((listOne.toString().subString(1, listOne.length() - 1) + ", " + listTwo.toString().subString(1, listTwo.length() - 1)).split(", ")));
如果丢弃泛型,这应该符合JDK 1.4(尽管我没有测试过)。也不建议用于生产代码; - )