Java list of list of String



我有版本列表(字符串),我想为每个版本的列表列表

List<List<String>> releases = new ArrayList<List<String>>();
def list = ["7.5.9", "7.5.8", "7.5.7", "7.5.6", "7.5.5", "7.5.4", "7.5.3", "7.5.2", "7.5.1", "7.5.0", "6.5.1", "6.5.0"];

我想收集每一个版本1.0.0, 1.0.1, 1.0.2,第二个1.5.0,1.5.1版本列表第三个版本列表2.0.0…等等,对于每个版本

由于发布版本有两位数字,输入列表可以使用Collectors.groupingBy按前缀分组(从而获得String, List<String>的映射),然后使用Collectors.collectingAndThen对版本列表进行排序:

List<List<String>> versions = new ArrayList<>(
list
.stream()
.collect(Collectors.groupingBy(
str -> str.substring(0, str.lastIndexOf('.')),
Collectors.collectingAndThen(
Collectors.toList(),
(List<String> lst) -> { lst.sort(String::compareTo); return lst; }
)
))
.values() // Collection<List<String>>
);
versions.forEach(System.out::println);

输出:

[1.0.0, 1.0.1, 1.0.2]
[2.0.0]
[3.0.0, 3.0.1]
[1.5.0, 1.5.1]
[2.5.0]
[3.5.0]

上面的代码假设版本中发布部分的格式总是至少有两个点(主要版本和次要版本)。

如果某些版本可能不符合初始格式(例如,有0.11.0.2.1),则以下分组条件应该可以正常工作:str -> str.substring(0, str.indexOf('.', str.indexOf('.') + 1) + 1),-假定释放前缀至少包含一个.点,最多包含两个点。


Groovy实现示例:

def list = ["3.5.0", "3.0.1", "3.0.0", "2.5.0", "2.0.0", "1.5.1", "1.5.0", "1.0.2", "1.0.1", "1.0.0"]
def versions = new ArrayList<> (list.groupBy { 
it.substring(0, it.lastIndexOf('.')) 
}.values())
.each { it.sort() }
versions.each {println it }

输出:

[3.5.0]
[3.0.0, 3.0.1]
[2.5.0]
[2.0.0]
[1.5.0, 1.5.1]
[1.0.0, 1.0.1, 1.0.2]

更新

下面的Groovy代码修复了排序问题,并删除了最高版本以及空结果:

def list = ["3.5.0", "3.0.1", "3.0.0", "2.5.0", "2.0.0", "1.5.1", "1.5.0", "1.0.1", "1.0.0", 
"1.0.10", "1.0.11", "1.0.2", "1.0.3", "1.0.4", "1.0.5", "1.0.6", "1.0.7", "1.0.8", "1.0.9"]
def versions = new ArrayList<> (
list
.sort() // sort initial list
.groupBy {
it.substring(0, it.lastIndexOf('.')) 
}.values()
)
.each { it.sort{ a,b -> Integer.compare(
Integer.parseInt(a.substring(a.lastIndexOf('.') + 1)), 
Integer.parseInt(b.substring(b.lastIndexOf('.') + 1))
)}.removeAt(it.size() - 1) }
versions.removeIf { it.empty } // remove empty sublists if any found
versions.each {println it }

输出
[1.0.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.0.5, 1.0.6, 1.0.7, 1.0.8, 1.0.9, 1.0.10]
[1.5.0]
[3.0.0]

试试这个

public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("3.5.0");
list.add("3.0.1");
list.add("3.0.0");
list.add("2.5.0");
list.add("2.0.0");
list.add("1.5.1");
list.add("1.5.0");
list.add("1.0.2");
list.add("1.0.1");
list.add("1.0.0");
Collections.sort(list);
Map<String, List<String>> map = new TreeMap<>();
for (String e : list)
map.computeIfAbsent(e.replaceFirst("\.\d+$", ""), k -> new ArrayList<>()).add(e);
List<List<String>> releases = new ArrayList<>(map.values());
System.out.println(releases);
}

输出:

[[1.0.0, 1.0.1, 1.0.2], [1.5.0, 1.5.1], [2.0.0], [2.5.0], [3.0.0, 3.0.1], [3.5.0]]

使用流:

List<List<String>> versions =
list.stream()
.collect(Collectors.groupingBy(/* a function which extracts the version */))
.values()  /* gives you a Collection<List<String>>, stop here if you don't need it as an actual List */
.stream()
.collect(Collectors.toList());

一个"函数的例子,它提取版本"对于显示的值可以是:

value -> value.substring(0, value.lastIndexOf('.'))

下面是一个没有Java流和其他奇怪结构的纯习惯Groovy版本:

def list = ["7.5.9", "7.5.8", "7.5.7", "7.5.6", "7.5.5", "7.5.4", "7.5.3", "7.5.2", "7.5.1", "7.5.0", "6.5.1", "6.5.0"]
def collector = {
List asInts = it.split( /./ )*.toInteger()
[ sum:asInts.reverse().withIndex().collect{ v, ix -> 10.power( ix ) * v }.sum(), major:asInts[ 0 ], original:it ]
}
def listOfSublists = list.collect collector sort{ it.sum } groupBy{ it.major } values()*.collect{ it.original }
assert listOfSublists.toString() == '[[6.5.0, 6.5.1], [7.5.0, 7.5.1, 7.5.2, 7.5.3, 7.5.4, 7.5.5, 7.5.6, 7.5.7, 7.5.8, 7.5.9]]'

最新更新