java 8 中的拆分和循环

Split and Loop in java 8

我有这个问题想在 java 8 中解决,

我有一个由 .

连接的字符串
A.B.C.D

字符串中的字符数可以变化。

我有这个方法,它将字符串作为输入,它必须达到的深度级别数, 我必须循环遍历使用“.”对字符串进行拆分后得到的数字。然后去给定深度

private String getResponse (String str, int level) {
// for now, simply print the entire string first and then start removing last alphabet of it one by one till the value of level
// ex : str = A.B.C.D
// System.out.println("Doing a call with key as = " + str); => should give me A.B.C.D
// Apply logic of split 
// System.out.println("Doing a call with key as = " + str); => should give me A.B.C
// Split again
// System.out.println("Doing a call with key as = " + str); => should give me A.B
// this should go in loop till we reach the level
}

这可以在 java 8 内完成吗?

注:不使用Java8

求解
public class StringLoop {

    public static void main(String[] args) {

        getResponse("A.B.C.D", 2);

        System.out.println();
        getResponse("A.B.C.D", 3);

    }

    // Recursive function
    private static void getResponse (String str, int level) {

        if(level < 0 || str.equals(""))
            return;

        // Prints out the current string
        System.out.println(str);

        int lastIndex = str.lastIndexOf(".");
        if(lastIndex == - 1)
            lastIndex = 0;

        // Remove content after last connector
        // Decrement level
        getResponse(str.substring(0, lastIndex), level - 1);
    }
}

输出:

A.B.C.D
A.B.C
A.B

A.B.C.D
A.B.C
A.B
A

这是 Java-8 的解决方案:

static void getResponse(String input, int level) {
    Stream.iterate(input, str -> {
        int pos = str.lastIndexOf('.');
        return pos == -1 ? "" : str.substring(0, pos);
    }).limit(level+1).forEach(System.out::println);
}

如果确定level不超过点数,可以省略检查:

static void getResponseUnsafe(String input, int level) {
    Stream.iterate(input, str -> str.substring(0, str.lastIndexOf('.')))
            .limit(level + 1).forEach(System.out::println);
}

您的评论提到使用 split(),所以这里有一个使用 split()Arrays.copyOfRange()(删除最后一个字母)和 String.Join() 来放置结果的示例的 Arrays.copyOfRange() 回到一起进行下一次递归调用。

public static void main(String[] args) {
    String string = "A.B.C.D";
    getResponse(string, 3);
    System.out.println();

    getResponse(string, 2);
    System.out.println();

    getResponse(string, 1);
    System.out.println();
}

private static void getResponse(String str, int level) {
    if (level < 0 || str.isEmpty())
        return;

    System.out.println(str);

    String[] strPieces = str.split("\.");
    if (strPieces.length > level) {
        getResponse(String.join(".", Arrays.copyOfRange(strPieces, 0, strPieces.length - 1)), level - 1);
    }
}

结果:

A.B.C.D
A.B.C
A.B
A

A.B.C.D
A.B.C
A.B

A.B.C.D
A.B.C

不需要循环,因为可以在单个 String.split 调用中将字符串拆分为数组。 (注意 String.split 采用正则表达式。)要处理 "level",只需从拆分数组的长度中减去它。不要复制数组子范围,而是将其转换为 List 并使用 subList():

String getResponse(String str, int level) {
    String[] splits = str.split("\.");
    if (level < 0 || level > splits.length) {
        throw new IllegalArgumentException();
    }
    return String.join(".", Arrays.asList(splits).subList(0, splits.length - level));
}

的输出
    for (int level = 0; level < 5; level++) {
        System.out.printf("level %d: %s%n", level, getResponse("A.B.C.D", level));
    }

level 0: A.B.C.D
level 1: A.B.C
level 2: A.B
level 3: A
level 4: 

请注意,这确实需要 Java 8,因为它需要 String.join()。 (但它不需要流甚至 lambda!)

如果您只对结果 String 感兴趣,则无需创建中间 String,也无需拆分成几个部分以便之后将它们拼凑在一起。只需遍历 String 中的匹配索引并创建一个结果 String:

static String getResponse(String str, int level) {
    for(int index=str.length(); index>0; index=str.lastIndexOf('.', index-1))
        if(level-- == 0) return str.substring(0, index);
    if(level==0) return "";
    throw new IllegalArgumentException(str+" has not enough dots");
}

这没有使用任何 Java 8 功能,但也很难想象 Java 8 功能如何改进这个简单的操作......