Home > Back-end >  How can I check a pattern in a SET and extract its value if it exists
How can I check a pattern in a SET and extract its value if it exists

Time:07-08

I have a set like below.

Set<String> name= new HashSet<String>();
        name.add("a-b-c");
        name.add("abc-type=unknown");
        name.add("xyz-type=a.b.c.d");
        name.add("log-value");

print

[a-b-c, log-value, abc-type=unknown, xyz-type=a.b.c.d]

I want to check if xyz-type exist and get its value "a.b.c.d" .

CodePudding user response:

Establish your inputs.

Set < String > inputs = Set.of( "a-b-c" , "abc-type=unknown" , "xyz-type=a.b.c.d" , "log-value" );

Loops

Call a method we invent for extracting the desired value. Our method returns an Optional because we may find nothing to report.

Optional < String > result = this.extract( "xyz-type" , inputs );

Report result.

System.out.println( "result = "   result );

Write that method.

We loop each input in our set. Keep in mind that a Set iterates in an unspecified order.

For each input string, try splitting on an EQUALS SIGN character. If this results in two parts, then proceed to see if the first part is our target string. If so, return the second part. If all else fails, return an empty Optional<String>.

private Optional < String > extract ( final String target , final Set < String > inputs )
{
    for ( String input : inputs )
    {
        String[] parts = input.split( "=" );
        if ( parts.length == 2 )
        {
            if ( Objects.equals( parts[ 0 ] , target ) )
            {
                return Optional.of( parts[ 1 ] );
            }
        }
    }
    return Optional.empty();
}

When run.

result = Optional[a.b.c.d]

Streams

This might possibly be done more briefly using streams. But as a student of Java, first master loops before trying streams.

Call our streams-based extract method.

Optional < String > result = this.extractViaStreams( "xyz-type=" , inputs );

Write that method.

private Optional < String > extractViaStreams ( final String target , final Set < String > inputs )
{
    return
            inputs
                    .stream()
                    .filter( input -> input.startsWith( target ) )
                    .map( input -> input.split( target )[ 1 ] )
                    .findAny();
}

Thanks owed to Arun Sudhakaran whose Comment about String#startsWith gave me the idea for this stream code.

CodePudding user response:

If you're going utilize these data multiple times it's probelly worth to transform this Set into a Map.

For one time use you can iterate over the set using a loop or a stream, try to split each element with a delimiter ("=") and check whether there's a match with the given key ("xyz-type").

That's how it can be done using Stream API:

public String getValue(Set<String> associatedSet, String delimiter, String key) {
    
    return associatedSet.stream()         // Stream<String>
        .map(str -> str.split(delimiter)) // Stream<String[]>
        .filter(arr -> arr.length == 2)
        .filter(arr -> arr[0].equals(key))
        .map(arr -> arr[1])              // Stream<String>
        .findFirst()                     // Optional<String>
        .orElse("no such key"); // or .orElseThrow() depending on you needs
}

A that how you can generate a Map using streams, assuming that all "keys" are unique:

public Map<String, String> toMap(Set<String> associatedSet, String delimiter) {
    
    return associatedSet.stream()         // Stream<String>
        .map(str -> str.split(delimiter)) // Stream<String[]>
        .collect(Collectors.toMap(
            arr -> arr[0],
            arr -> arr.length == 2 ? arr[1] : "" // if delimiter is not present (length == 1) the key would be associated with an empty string
        ));
}

If there could be multiple occurrences of the same "key" you can use the following approach:

public Map<String, List<String>> toMap(Set<String> associatedSet, String delimiter) {
    
    return associatedSet.stream()         // Stream<String>
        .map(str -> str.split(delimiter)) // Stream<String[]>
        .collect(Collectors.groupingBy(
            arr -> arr[0],
            Collectors.mapping(arr -> arr.length == 2 ? arr[1] : "",
                Collectors.toList())
        ));
}
  • Related