Как закрепить два списка Java

У меня есть 2 списка:

List<String> subjectArr = Arrays.asList<String>("aa", "bb", "cc");
List<Long> numArr = Arrays.asList<Long>(2L, 6L, 4L);

Как мне создать новый List и закрепить в нем два списка?

List<?> subjectNumArr = zip(subjectArr, numArr);
// subjectNumArr == [{'aa',2},{'bb',6},{'cc',4}]

Ответ 1

Здесь решение Java-8 с использованием класса Pair (как в ответе @ZhekaKozlov):

public static <A, B> List<Pair<A, B>> zipJava8(List<A> as, List<B> bs) {
    return IntStream.range(0, Math.min(as.size(), bs.size()))
            .mapToObj(i -> new Pair<>(as.get(i), bs.get(i)))
            .collect(Collectors.toList());
}

Ответ 2

Используйте ArrayList Map.Entry<String, Long>, проверяя, что оба arraylists имеют одинаковый размер (как вам кажется, ваше требование), например:

List<Map.Entry<String,Long>> subjectNumArr = new ArrayList<>(numArr.size());
if (subjectArr.size() == numArr.size()) {
    for (int i = 0; i < subjectArr.size(); ++i) {
        subjectNumArr.add(new AbstractMap.SimpleEntry<String, Long>(subjectArr.get(i), numArr.get(i));
    }   
}

Чтобы весь код вам нужен!

Затем, чтобы перебрать результаты, используйте что-то вроде:

for (Map.Entry<String, Long> entry : subjectNumArr) {
    String key = entry.getKey(); 
    Long value = entry.getValue();
}

или, вы можете просто получить пару в позиции я (сохраняя порядок вставки), используя:

Map.Entry<String, Long> entry = subjectNumArr.get(i);

Это также может содержать повторяющиеся записи, в отличие от предлагаемого мной решения карты, не требуя определения вашего собственного класса (пары).

Ответ 3

Операция, которую вы хотите, называется zipping.

Сначала вам нужна структура данных, которая содержит два объекта. Назовем его Pair:

public final class Pair<A, B> {
  private final A left;
  private final B right;

  public Pair(A left, B right) {
    this.left = left;
    this.right = right;
  }

  public A left() { return left; }
  public B right() { return right; }

  public String toString() {
    return "{" + left + "," + right + "}";
  }
}

Затем вам нужно реализовать метод zip:

public static <A, B> List<Pair<A, B>> zip(List<A> as, List<B> bs) {
  Iterator<A> it1 = as.iterator();
  Iterator<B> it2 = bs.iterator();
  List<Pair<A, B>> result = new ArrayList<>();
  while (it1.hasNext() && it2.hasNext()) {
    result.add(new Pair<A, B>(it1.next(), it2.next()));
  }
  return result;
}

И, наконец, использование zip:

zip(subjectArr, numArr);

Ответ 4

В соответствии с связанным вопросом вы можете использовать Guava ( >= 21.0) для этого:

List<String> subjectArr = Arrays.asList("aa", "bb", "cc");
List<Long> numArr = Arrays.asList(2L, 6L, 4L);
List<Pair> pairs = Streams.zip(subjectArr.stream(), numArr.stream(), Pair::new)
        .collect(Collectors.toList());

Ответ 5

Я согласен с vefthym, однако, если вам нужно сделать с помощью списка, тогда создайте класс, как показано ниже:

class DirtyCoding{
   String subject;
   int numbr;
}

Затем перейдите по списку, создайте объект DirtyCoding, заполните его и добавьте, затем добавьте его в List<DirtyCoding>.

Ответ 6

Используйте один из ответов потоков Zipping с помощью JDK8 с lambda (java.util.stream.Streams.zip) для zip и применения функции в то же время

например. Использование сжатого потока:

<A,B,C>  Stream<C> zipped(List<A> lista, List<B> listb, BiFunction<A,B,C> zipper){
     int shortestLength = Math.min(lista.size(),listb.size());
     return IntStream.range(0,shortestLength).mapToObject( i -> {
          return zipper.apply(lista.get(i), listb.get(i));
     });        
}

для которого вы также можете использовать Guava Streams.zip()

Ответ 7

Вы должны создать ArrayList of List:

ArrayList<List> subjectNumArr = new ArrayList<>();
Iterator iter = subjectArr.iterator();
int count=0;
while(iter.hasNext()){
    subjectNumArr.add(Arrays.asList(iter.next(),numArr.get[count++]);
}

Ответ 8

Мои идеи:

  • Определите класс для ваших пар. Это делает ваш код расширяемым (т.е. Если вы хотите добавить третье поле).
  • Определите свои списки с помощью удобного метода Arrays.asList. Это легко понять, коротко и автоматически генерирует общие коллекции.
  • Используйте суперклассы или интерфейсы как переменные типы. Я использовал List в примере, возможно, Collection будет еще лучше. Только объявляйте переменные как ArrayList, если вам нужен такой список. Это даст вам возможность использовать другие реализации без необходимости менять код.

Я бы создал объекты Pair следующим образом:

import java.util.*;

class Pair {
    String subject;
    Long num;
}

public class Snippet {

    public static void main(String[] args) {
        List<String> subjectArr = Arrays.asList("aa", "bb", "cc");
        List<Long> numArr = Arrays.asList(2l,6l,4l);

        // create result list
        List<Pair> pairs = new ArrayList<>();

        // determine result size
        int length = Math.min(subjectArr.size(), numArr.size());

        // create pairs
        for (int position = 0; position < length; position++) {
            Pair pair = new Pair();
            pair.subject = subjectArr.get(position);
            pair.num = numArr.get(position);
            pairs.add(pair);
        }
    }
}

Ответ 9

Чтобы получить Iterator<C> из Iterator<A>, Iterator<B> и BiFunction<A, B, C>:

public static <A, B, C> Iterator<C> map(Iterator<A> a, Iterator<B> b, BiFunction<A, B, C> f) {
    return new Iterator<C>() {
        public boolean hasNext() {
            return a.hasNext() && b.hasNext(); // This uses the shorter of the two 'Iterator's.
        }

        public C next() {
            return f.apply(a.next(), b.next());
        }
    };
}

Ответ 10

В Java 8: Вы можете сделать это в одной строке, используя класс Stream и Collectors.

В Java 7/6/5:

List list = new ArrayList();

        if(subjectArr.size() == numArr.size())
        {
            for (int i = 0; i < subjectArr.size(); i++) { // Loop through every subject/name
                list.add(subjectArr.get(i) + " " + numArr.get(i)); // Concat the two, and add it
            }
        }