Eğer varsa , Java 8'in özelliklerini kullanarak bunu aynı yineleme sırasına sahip tüm nesneleri içeren List<List<Object>>bir haline nasıl dönüştürebilirim List<Object>?
Eğer varsa , Java 8'in özelliklerini kullanarak bunu aynı yineleme sırasına sahip tüm nesneleri içeren List<List<Object>>bir haline nasıl dönüştürebilirim List<Object>?
Yanıtlar:
Sen kullanabilirsiniz flatMaptek Çayı'nın içine (Akışları dönüştürerek sonra) iç listelerini dümdüz ve sonra bir liste halinde sonucunu toplamak için:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
Class::methodilk başta biraz garip hissettiriyor, ancak ne tür bir nesneden eşlediğinizi açıklamanın yararı var. Bu, akarsularda kaybettiğiniz bir şeydir.
Üzerindeki flatMapyöntem Streambu listeleri sizin için kesinlikle düzleştirebilir, ancak Streamöğe için nesneler, sonra Streamsonuç için bir a oluşturmanız gerekir .
Tüm bu Streamnesnelere ihtiyacınız yok . İşte görevi gerçekleştirmek için basit, özlü kod.
// listOfLists is a List<List<Object>>.
List<Object> result = new ArrayList<>();
listOfLists.forEach(result::addAll);
Bir için Listolan Iterable, bu kod çağırır yöntemi devralınır (Java 8 özelliği), . forEachIterable
IterableTüm öğeler işleninceye veya eylem bir istisna atana kadar her öğesinin verilen eylemini gerçekleştirir . İşlemler, bu sipariş belirtilirse, yineleme sırasında gerçekleştirilir.
Ve a List'nın Iteratoröğeleri sıralı olarak döndürür.
İçin Consumerbu kod List.addAll, iç liste öğelerini sırayla eklemek için Java 8 öncesi yönteme bir yöntem başvurusunda (Java 8 özelliği) geçer .
Belirtilen koleksiyondaki tüm öğeleri, belirtilen koleksiyonun yineleyicisi tarafından döndürülme sırasına göre bu listenin sonuna ekler (isteğe bağlı işlem).
Eclipse Collections'takiflatCollect() kalıbı kullanabilirsiniz .
MutableList<List<Object>> list = Lists.mutable.empty();
MutableList<Object> flat = list.flatCollect(each -> each);
Listeyi şuradan değiştiremiyorsanız List:
List<List<Object>> list = new ArrayList<>();
List<Object> flat = ListAdapter.adapt(list).flatCollect(each -> each);
Not: Eclipse Koleksiyonlarına katkıda bulunuyorum.
@Saravana'nın belirttiği gibi:
flatmap daha iyidir, ancak bunu başarmanın başka yolları da vardır
listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
Özetlemek gerekirse, aşağıdakileri elde etmenin birkaç yolu vardır:
private <T> List<T> mergeOne(Stream<List<T>> listStream) {
return listStream.flatMap(List::stream).collect(toList());
}
private <T> List<T> mergeTwo(Stream<List<T>> listStream) {
List<T> result = new ArrayList<>();
listStream.forEach(result::addAll);
return result;
}
private <T> List<T> mergeThree(Stream<List<T>> listStream) {
return listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
}
private <T> List<T> mergeFour(Stream<List<T>> listStream) {
return listStream.reduce((l1, l2) -> {
List<T> l = new ArrayList<>(l1);
l.addAll(l2);
return l;
}).orElse(new ArrayList<>());
}
private <T> List<T> mergeFive(Stream<List<T>> listStream) {
return listStream.collect(ArrayList::new, List::addAll, List::addAll);
}
Sadece bir tane daha senaryo gibi açıklamak istiyorum List<Documents>, bu liste gibi diğer belgelerin birkaç liste içeren List<Excel>, List<Word>, List<PowerPoint>. Yani yapı
class A {
List<Documents> documentList;
}
class Documents {
List<Excel> excels;
List<Word> words;
List<PowerPoint> ppt;
}
Şimdi Excel'i yalnızca belgelerden yinelemek istiyorsanız, aşağıdaki gibi bir şey yapın ..
Yani kod
List<Documents> documentList = new A().getDocumentList();
//check documentList as not null
Optional<Excel> excelOptional = documentList.stream()
.map(doc -> doc.getExcel())
.flatMap(List::stream).findFirst();
if(excelOptional.isPresent()){
Excel exl = optionalExcel.get();
// now get the value what you want.
}
Umarım bu kodlama sırasında birinin sorununu çözebilir ...
Bunun için flatmap kullanabiliriz, lütfen aşağıdaki kodlara bakın:
List<Integer> i1= Arrays.asList(1, 2, 3, 4);
List<Integer> i2= Arrays.asList(5, 6, 7, 8);
List<List<Integer>> ii= Arrays.asList(i1, i2);
System.out.println("List<List<Integer>>"+ii);
List<Integer> flat=ii.stream().flatMap(l-> l.stream()).collect(Collectors.toList());
System.out.println("Flattened to List<Integer>"+flat);
Eran'ın cevabında en büyük cevap olan bir genişleme, eğer bir grup liste katmanınız varsa, onları parçalamaya devam edebilirsiniz.
Bu ayrıca gerektiğinde katmanlardan aşağı inerken kullanışlı bir filtreleme yolu ile birlikte gelir.
Yani mesela:
List<List<List<List<List<List<Object>>>>>> multiLayeredList = ...
List<Object> objectList = multiLayeredList
.stream()
.flatmap(someList1 -> someList1
.stream()
.filter(...Optional...))
.flatmap(someList2 -> someList2
.stream()
.filter(...Optional...))
.flatmap(someList3 -> someList3
.stream()
.filter(...Optional...))
...
.collect(Collectors.toList())
Bu SQL'de SELECT ifadeleri içinde SELECT ifadelerine sahip olmaya benzer.
Yöntem bir dönüştürmek List<List>için List:
listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
Bu örneğe bakın:
public class Example {
public static void main(String[] args) {
List<List<String>> listOfLists = Collections.singletonList(Arrays.asList("a", "b", "v"));
List<String> list = listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
System.out.println("listOfLists => " + listOfLists);
System.out.println("list => " + list);
}
}
Yazdırır:
listOfLists => [[a, b, c]]
list => [a, b, c]
:::)