我有版本列表(字符串),我想为每个版本的列表列表
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.1
或1.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]]'