Java 基于相似索引收集列表集合
我有一个像这样的收藏:Java 基于相似索引收集列表集合,java,loops,collections,java-8,iteration,Java,Loops,Collections,Java 8,Iteration,我有一个像这样的收藏: List firstList 我想将类似的模式列表组合在一起: List secondList 但按索引分组 说 我想将此集合分组为 secondList [1]: 0 = {Object A}" 1 = {Object A}" secondList [2]: 0 = {Object B}" 1 = {Object B}" secondList [3]: 0 = {Object C}" 1 = {Object C}" 到目前为止,
List firstList
我想将类似的模式列表组合在一起:
List secondList
但按索引分组
说
我想将此集合分组为
secondList [1]:
0 = {Object A}"
1 = {Object A}"
secondList [2]:
0 = {Object B}"
1 = {Object B}"
secondList [3]:
0 = {Object C}"
1 = {Object C}"
到目前为止,我所尝试的是
for (int i = 0; i <firstList.size() ; i++) {
List<Object> list = firstList.get(i);
List<Object> rlPr = new ArrayList<>();
for (int j = 0; j <list.size()-1; j++) {
rlPr.add(list.get(i));
}
secondList.add(rlPr);
}
for(inti=0;i假设主列表中的列表大小都相同,您可以这样做
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class OhCrikey {
public static void main(String[] args) {
List<List<String>> lists = Arrays.asList(
Arrays.asList("1a", "2a", "3a"),
Arrays.asList("1b", "2b", "3b"),
Arrays.asList("1c", "2c", "3c")
);
List<List<String>> result = transform(lists);
result.forEach(System.out::println);
}
private static <T> List<List<T>> transform(List<List<T>> lists) {
if(lists == null || lists.isEmpty()) {
return Collections.emptyList();
}
// Check each sub-list contains the same number of elements
checkAllSameSize(lists);
// Initialise the results list
List<List<T>> result = new ArrayList<>();
// Get the size of each sub-list
int totalLists = lists.get(0).size();
// Fill up the results list with 'totalLists' empty lists
for(int k = 0; k < totalLists; k++) {
result.add(new ArrayList<>());
}
// For each input list...
lists.forEach(list -> {
// Iterate over it and add the kth element to the kth result list.
for(int k = 0; k < list.size(); k++) {
result.get(k).add(list.get(k));
}
});
return result;
}
private static <T> void checkAllSameSize(List<List<T>> lists) {
int size = lists.get(0).size();
// Make sure each list has the same size as the first list
lists.forEach(list -> {
if(list.size() != size) {
throw new AssertionError("All child lists must have same number of elements.");
}
});
}
}
您可以使用映射
按索引对值进行分组:
Map<Integer, List<Object>> map = new TreeMap<>();
for (List<Object> objects : firstList) {
for (int i = 0, l = objects.size(); i < l; i++) {
map.computeIfAbsent(i, k -> new ArrayList<>()).add(objects.get(i));
}
}
首先,获取子列表的最大长度。在您的例子中,两者都是3。迭代所有这些索引,从每个子列表中获取该索引处的值,并将这些值收集到新的子列表中
final int maxLengthOfSublist = list1.stream().mapToInt(List::size).max().orElse(0);
final List<List<Integer>> list2 = IntStream.range(0, maxLengthOfSublist)
.mapToObj(idx -> list1.stream()
.filter(sublist -> idx < sublist.size())
.map(sublist -> sublist.get(idx))
.collect(Collectors.toList())
)
.collect(Collectors.toList());
final int maxlengthhofsublist=list1.stream().mapToInt(List::size).max().orElse(0);
最终列表列表2=IntStream.range(0,MaxLengthofPublist)
.mapToObj(idx->list1.stream()
.filter(子列表->idx子列表.get(idx))
.collect(收集器.toList())
)
.collect(Collectors.toList());
即使子列表的长度不同,这也会起作用。这样做的一种流式方式是(将对象
替换为自定义对象
):
List secondList=新建ArrayList(//集合到ArrayList
firstList.stream()//流
.flatMap(集合::流)//流
.collect(Collectors.groupingBy(Function.identity())//Map
.values());//集合
@michael Correct.这是一个输入错误。我已经纠正了同样的错误。谢谢!尝试使用索引作为键的映射,在解析源列表后从映射中获取值,这样您就不想“按索引分组”,但按项目分组?您似乎在丢弃原始索引,并多次维护同一对象。这是最简洁、优雅的解决方案,也是最具表现力的解决方案。如果possible@FedericoPeraltaSchaffner谢谢。我自己也没想到这会是一项如此简单的任务,我真的以为会包括更多的复杂性:)如其他评论所述,这是所有解决方案中最优雅的。谢谢@Lino.inti=0,l=objects.size();i
为什么不干脆inti=0;i
?@Lino我不这么认为。您牺牲了可读性,根本没有任何实际的性能优势。如果您关心方法调用,那么应该在循环之前初始化变量,给它一个有意义的名称,如length
,并将其设置为final。对任何有效的最终变量使用循环初始值设定项都是错误的,因为当我读取它时,我需要扫描整个循环体,以确保您没有更改它。工作正常。但使用的逻辑相当大。相比之下,Lino的答案似乎有点紧凑。不同大小列表的通用解决方案
Map<Integer, List<Object>> map = new TreeMap<>();
for (List<Object> objects : firstList) {
for (int i = 0, l = objects.size(); i < l; i++) {
map.computeIfAbsent(i, k -> new ArrayList<>()).add(objects.get(i));
}
}
List<List<Object>> secondList = new ArrayList<>(map.values());
final int maxLengthOfSublist = list1.stream().mapToInt(List::size).max().orElse(0);
final List<List<Integer>> list2 = IntStream.range(0, maxLengthOfSublist)
.mapToObj(idx -> list1.stream()
.filter(sublist -> idx < sublist.size())
.map(sublist -> sublist.get(idx))
.collect(Collectors.toList())
)
.collect(Collectors.toList());
List<List<CustomObject>> secondList = new ArrayList<>( // Collection to ArrayList
firstList.stream() // Stream<List<CustomObject>>
.flatMap(Collection::stream) // Stream<CustomObject>
.collect(Collectors.groupingBy(Function.identity())) // Map<CustomObject, List<CustomObject>>
.values()); // Collection<List<CustomObject>>