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");
[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())
));
}