2016-06-08 10 views
8

mümkün mü [1,2,3,4,5], [6,7,8], [9,0] koleksiyonları vardır. [1,6,9,2,7,0,3,8,4,5] - Aşağıdaki sonuç almak için Java 8 akışı API üzerinden bu koleksiyonları serpiştirmek için adım adım elde döngüler önlemek için herhangi bir şekilde? Akış API ile daha basit bir yol varsa.flatMap() veya .collect() eşit olarak birden fazla koleksiyon

cevap

8

Emin değilim ama dikkate almak tüm listelerin endeksleri üzerinden bir akışı kullanarak bunu yapabilirsiniz: Bu büyük boyutunu alır

static <T> List<T> interleave(List<List<T>> lists) { 
    int maxSize = lists.stream().mapToInt(List::size).max().orElse(0); 
    return IntStream.range(0, maxSize) 
        .boxed() 
        .flatMap(i -> lists.stream().filter(l -> i < l.size()).map(l -> l.get(i))) 
        .collect(Collectors.toList()); 
} 

verilen listelerde liste. Her indeks için, o zaman, bu indeksdeki her bir listenin elemanları tarafından oluşturulan bir akım ile düz eşleştirilir (eğer eleman mevcutsa).

Sonra protonpack kütüphaneyi kullanma

public static void main(String[] args) { 
    List<Integer> list1 = Arrays.asList(1,2,3,4,5); 
    List<Integer> list2 = Arrays.asList(6,7,8); 
    List<Integer> list3 = Arrays.asList(9,0); 
    System.out.println(interleave(Arrays.asList(list1, list2, list3))); // [1, 6, 9, 2, 7, 0, 3, 8, 4, 5] 
} 

ile kullanabilirsiniz, sadece bunu yapmak için yöntem interleave kullanabilirsiniz: Çok iyi bir çözüm

List<Stream<Integer>> lists = Arrays.asList(list1.stream(), list2.stream(), list3.stream()); 
List<Integer> result = StreamUtils.interleave(Selectors.roundRobin(), lists).collect(Collectors.toList()); 
System.out.println(result); 
+1

, bir performans cezası olacaktır. İlk çözümde, bu, ikinci hakkında bilmiyorum. Daha sonra, LinkedList bazen kötü performans gösteriyor, belki de o kadar yeni değil. –

0

olsa. Sadece

List<String> listA = Arrays.asList("a1","a2","a3","a4"); 
    List<String> listB = Arrays.asList("b1","b2","b3","b4"); 
    List<String> listC = Arrays.asList("c1","c2","c3","c4"); 
    List<String> combined = Stream.of(listA, listB, listC).flatMap(Collection::stream).collect(Collectors.toList()); 
    AtomicInteger index = new AtomicInteger(); 
    List<String> list1 = combined 
      .stream().filter(x -> index.incrementAndGet() % 4 ==1).collect(Collectors.toList()); 
    index.set(0); 
    List<String> list2 = combined 
    .stream().filter(x -> index.incrementAndGet() % 4 ==2).collect(Collectors.toList()); 
    index.set(0); 
    List<String> list3 = combined 
    .stream().filter(x -> index.incrementAndGet() % 4 ==3).collect(Collectors.toList()); 
    index.set(0); 
    List<String> list0 = combined 
      .stream().filter(x -> index.incrementAndGet() % 4 ==0).collect(Collectors.toList()); 
    List<String> desiredOutput = Stream.of(list1, list2, list3,list0).flatMap(Collection::stream).collect(Collectors.toList()); 
    System.out.println(String.join(",", desiredOutput)); 
0

deneyin ben Tunaki yanıtını gibi ve üzerinde biraz daha çalışma sürem:

static <T> List<T> interleave(List<? extends Collection<T>> lists) { 
    int maxSize = lists.stream().mapToInt(Collection::size).max().orElse(0); 
    List<Iterator<T>> iterators = lists.stream().map(l -> l.stream().iterator()).collect(Collectors.toList()); 
    return IntStream.range(0, maxSize) 
      .boxed() 
      .flatMap(i -> iterators.stream().filter(it -> it.hasNext()).map(it -> it.next())) 
      .collect(Collectors.toList()); 
} 

Ben de akışları olarak biz ilk listeleri tedavi edebilir görmek istedim, biz ortaya çıktı can. Bir yan etki olarak, biz (yani gerçekten LinkedList çok uzun olsaydı, biz bunu önlemek isterim) bir listede get(i) kaçının. Orijinal listelerin maksimum uzunluğunu bilmeden yapmanın bir yolunu bulamadım. listeleri uzun ve rasgele erişim (diyelim ki, LinkedList) ise

İlgili konular