How do I join two lists in Java?

后端 未结 30 1709
旧巷少年郎
旧巷少年郎 2020-11-22 14:36

Conditions: do not modifiy the original lists; JDK only, no external libraries. Bonus points for a one-liner or a JDK 1.3 version.

Is there a simpler way than:

相关标签:
30条回答
  • 2020-11-22 15:26

    If you want to do this statically you can the following.

    The examples uses 2 EnumSets in natural-order (==Enum-order) A, B and joins then in an ALL list.

    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);
                      }}
                  );
    
    0 讨论(0)
  • 2020-11-22 15:28
    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;
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 15:29

    Found this question looking to concatenate arbitrary amount of lists, not minding external libraries. So, perhaps it will help someone else:

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

    Useful if you want to apply the same logic to a number of different collections in one for().

    0 讨论(0)
  • 2020-11-22 15:29

    A little shorter would be:

    List<String> newList = new ArrayList<String>(listOne);
    newList.addAll(listTwo);
    
    0 讨论(0)
  • 2020-11-22 15:30

    In Java 8:

    List<String> newList = Stream.concat(listOne.stream(), listTwo.stream())
                                 .collect(Collectors.toList());
    
    0 讨论(0)
  • 2020-11-22 15:33

    Java 8 (Stream.of and Stream.concat)

    The proposed solution is for three lists though it can be applied for two lists as well. In Java 8 we can make use of Stream.of or Stream.concat as:

    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 takes two streams as input and creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream. As we have three lists we have used this method (Stream.concat) two times.

    We can also write a utility class with a method that takes any number of lists (using varargs) and returns a concatenated list as:

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

    Then we can make use of this method as:

    List<String> result3 = Utils.concatenateLists(list1,list2,list3);
    
    0 讨论(0)
提交回复
热议问题