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 flatMap
tek Ç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::method
ilk 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 flatMap
yöntem Stream
bu listeleri sizin için kesinlikle düzleştirebilir, ancak Stream
öğe için nesneler, sonra Stream
sonuç için bir a oluşturmanız gerekir .
Tüm bu Stream
nesnelere 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 List
olan Iterable
, bu kod çağırır yöntemi devralınır (Java 8 özelliği), . forEach
Iterable
Iterable
Tü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 Consumer
bu 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]
::
:)