Reputation: 307
I have a condition where there are some checks to be made in order to create an object.
I am using Stream
s for this, and I'm having a tough time in getting this done.
The input is a HashMap
object with key/value pairs and output should be below.
| userrole | userid | username | output |
|------------|--------|----------|----------|
| "" (blank) | 111 | amathews | 111 |
| "" | | amathews | amathews |
| Admin | 111 | amathews | 111 |
| Admin | 111 | "" | 111 |
| Admin | | amathews | Admin |
This is how the precedence is: userid>userrole>username.
Each HashMap
object will contain userrole/username/userid as key and its values along with other key/value pairs.
We will have a bunch of nested if/else statements to accomplish this task in prior versions of Java.
Here is my code:
map.entrySet().stream()
.filter(e -> e.getValue() instanceof String || e.getValue() instanceof Integer)
.filter(e -> e.getKey().contains("userrole") || e.getKey().contains("userid") || e.getKey().contains("username") )
.map(e -> e.getValue())
.collect(Collectors.toList());
I know that the way I have written map function in the Stream
is not correct too.
How to accomplish this in java 8? I do not know how to add the nested if/else part here.
Edit : Sorry If I hadn't stated the problem precisely. Here is the code snippet:
public List<UserAction> getUserActionList(Map<String, String> map)
{
String userRole = map.get("userrole");
String userName = map.get("username");
String userId = map.get("userid");
String output = null;
// if userrole, userid and username are not null/empty, then output is userid
if(!checkForNullEmpty(userRole) && !checkForNullEmpty(userId) && !checkForNullEmpty(userName))
output = userId;
// if userrole and userid are null/empty and username is not empty/null, then output is username
else if(checkForNullEmpty(userRole) && checkForNullEmpty(userId) && !checkForNullEmpty(userName))
output = userName;
// if userid and username are null/empty and userrole is not empty/null, then output is userrole
else if(!checkForNullEmpty(userRole) && checkForNullEmpty(userId) && checkForNullEmpty(userName))
output = userRole;
List<UserAction> udList = new ArrayList<>();
// Add the map and output into a UserAction object
udList.add(new UserAction(map, output));
return udList;
}
I had handled only 3 conditions here as per the table. So this has to refactored to use java 8 Stream
s. I hope it makes sense now.
Upvotes: 4
Views: 14817
Reputation: 424993
If at least one of the values is guaranteed, you could refactor it like this:
public List<UserAction> getUserActionList(Map<String, String> map) {
return Stream.of("userid", "username", "userrole")
.map(map::get)
.filter(s -> !checkForNullEmpty(s))
.limit(1)
.map(output -> new UserAction(map, output))
.collect(Collectors.toList());
}
If it is not guaranteed that at least one value will be non-null, it's a little uglier, but not too bad:
public List<UserAction> getUserActionList(Map<String, String> map) {
return Stream.of("userid", "username", "userrole")
.map(map::get)
.filter(s -> !checkForNullEmpty(s))
.limit(1)
.map(output -> new UserAction(map, output))
.map(Collections::singletonList)
.findFirst()
.orElseGet(() -> Arrays.asList(new UserAction(map, null)));
}
Upvotes: 3
Reputation: 5897
It's not really clear about the task you need to accomplish, but in general, everything that you need to write in your if
statements you can do with filter()
method from Stream API
. Then, in map()
method you'd have the exact logic which is needed to be done with the data (e.g. transforming it to some other type or getting values which are needed). collect()
method is used to create a result from the Stream
, e.g. list, set, map, single object or anything else. For example:
map.entrySet().stream()
.filter(e -> {
// filter the data here, so if isStrOrInt or containsUserData is false - we will not have it in map() method
boolean isStrOrInt = e.getValue() instanceof String || e.getValue() instanceof Integer;
boolean containsUserData = e.getKey().contains("userrole") || e.getKey().contains("userid") || e.getKey().contains("username");
return isStrOrInt && containsUserData;
})
.map(e -> {
if (e.getKey().contains("userrole")) {
// do something
}
// some more logic here
return e.getValue();
})
.collect(Collectors.toList());
// or e.g. .reduce((value1, value2) -> value1 + value2);
If you need to create a single object in the end, you would probably need reduce()
method. I recommend you to check reduction operations, general information about Stream API to understand how they work.
Upvotes: 2