Is there a way to write below piece of code in java 8 format?

149 Views Asked by At

I am writing a piece of code for creating partition key for a DDB table. I have long name in dotted format which can have as many names as possible seperated by "."

e.g. qw.er.ty.ui

I want the below method to return the subname of the above name as "SUBNAME_qwer". i.e "SUBNAME_" + firstname + secondname. Where first name is the string before the first dot in the long name. and second name is the string after the first dot and before the second dot.

I don't want to make any changes to behaviour of the code but want to write it in JAVA 8 way. Is it possible?

Snippet 1:

    //name is a dotted format hierarchical name. e.g. n.x.y.c
    String getFirstTwoSubNames(final String name) {
        if (name == null) {
            throw new IllegalArgumentException("can't be null");
        }
        if (name.contains(".")) {
            String[] subNames = name.split("\\.");
            String firstTwoSubNames = subNames[0] + subNames[1];
            return String.join("_", "SUBNAME", firstTwoSubNames);

        } else {
            throw new IllegalArgumentException("Invalid format");
        }
    }

Update 1: Sorry for writing my question so poorly. I am new to JAVA 8 and stack overflow. The ask here is to remove the imperative coding and adopt functional coding style with JAVA 8. So far with the help of @Alex Rudenko's answer I am able to convert the above code to functional JAVA 8-y code as follows:

Snippet 2:

 String getFirstTwoSubNames(final String name) {
       return "SUBNAME_" + Arrays.stream(Optional.ofNullable(name)
                    .orElseThrow(IllegalArgumentException::new)
                    .split("\\."))
                    .limit(2)
                    .collect(Collectors.joining(""));
    }

As you can see I am missing the logic of throwing invalid exception from the code snippet 1. I wish to include this in code snippet 2 in functional way. Hope this brings more clarity to my question.

1

There are 1 best solutions below

3
On

A "Java 8"-like solution could be using Stream.limit to pick up only 2 sub-names and Collectors.joining("").

The check name.contains(".") may be removed, it can be defined after splitting the input string.

String getFirstTwoSubNames(final String name) {
    if (name == null) {
        throw new IllegalArgumentException("can't be null");
    }
    String[] subNames = name.split("\\.");
    if (subNames.length < 2) {
        throw new IllegalArgumentException("Invalid format");
    }
    return "SUBNAME_" + Arrays.stream(subNames).limit(2).collect(Collectors.joining(""));
}

Update

The updated code snippet #2 may be refactored to separate validation code into separate method, so that getFirstTwoSubnames use only valid name:

static String validName(String name) {
    return Stream.of(Optional.ofNullable(name).orElseThrow(NullNameException::new))
                 .filter(name -> name.contains("."))
                 .findFirst()
                 .orElseThrow(MinSubnamesException::new);
}

static String getFirstTwoSubNames(final String name) {
    return "SUBNAME_" + Arrays.stream(validName(name).split("\\."))
                              .limit(2)
                              .collect(Collectors.joining());
}

//--------
// customized exceptions
class NullNameException extends NullPointerException {
    public NullNameException() {
        super("Name cannot be null");
    }
}

class MinSubnamesException extends IllegalArgumentException {
    public MinSubnamesException() {
        super("A name must contain at least two sub-names separated with dot `.`");
    }
}