Java 字符串列表列表

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 的第三个列表......每个版本依此类推

使用流:

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('.'))

由于发布版本有两位数字,输入列表可以使用 Collectors.groupingBy 按前缀分组(从而得到 String, List<String> 的映射),然后使用 Collectors.groupingBy 对版本列表进行排序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), - 假定发布前缀包含至少 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]]

下面是一个纯粹惯用的 Groovy 版本 w/o Java 流和其他奇怪的结构:

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]]'