I am looking to replace the following code with Java lambda expressions.In the below case I need to come out the loop if the match is found and also set boolean to true in order to assert a condition
Long teamId;
boolean matchFound = false;
List<WorkflowSubscriptions> workflowSubscriptionsList = fetchSubscriptions();
for (WorkflowSubscriptions workflowSubscriptions : workflowSubscriptionsList) {
for (WorkflowCompositeInfo workflowCompositeInfo : workflowSubscriptions.getWorkflowCompositeInfo()) {
if (workflowCompositeInfo.getId() > 0 && workflowCompositeId == workflowCompositeId.intValue()) {
teamId = Long.valueOf(workflowSubscriptions.getId());
matchFound = true;
}
}
}
if (!matchFound) {
throw new CustomParameterizedException("Workflow does not have valid subscriptions");
}
Try this:
fetchSubscriptions().stream()
.filter(p -> w.getId() > 0 && workflowCompositeId == w.intValue())
.limit(1)
.forEach(w -> {teamId = Long.valueOf(w); matchFound = true;} );
UPDATE
To avoid errors about modifying a final variable. You can simply create a value class:
public class MyValue {
public boolean matchFound;
public Long teamId;
}
Then:
final MyValue value = new MyValue();
fetchSubscriptions().stream()
.filter(p -> w.getId() > 0 && workflowCompositeId == w.intValue())
.limit(1)
.forEach(w -> {value.teamId = Long.valueOf(w); value.matchFound = true;} );
// Here, find your data in value.teamId and value.matchFound
Related
I wrote this boolean method but I want to make it shorter and smarter since there are 3 same lines with quite the same XPath.
Could anyone help me with this, please? thanks
public boolean VerifyKORSecDispaly() {
boolean a = driver
.findElement(By
.xpath("(//tr[#data-testid='row']//td[#class='kor'])[1]//span[#class='da']"))
.getText().contains("d");
boolean b = driver
.findElement(By
.xpath("(//tr[#data-testid='row']//td[#class='kor'])[2]//span[#class='da']"))
.getText().contains("d");
boolean c = driver
.findElement(By
.xpath("(//tr[#data-testid='row']//td[#class='kor'])[3]//span[#class='da']"))
.getText().contains("d");
if (a == true && b == true && c == true) {
return true;
} else {
return false;
}
}
You could use List<> since you use indexes in xpath.
//tr[#data-testid='row']//td[#class='kor'] <- this selector would return multiple elements
Based on these elements, we can find span[#class='da'] element.
Code:
public boolean VerifyKORSecDispaly() {
boolean a = doesRowTextContain(0, "d");
boolean b = doesRowTextContain(1, "d");
boolean c = doesRowTextContain(2, "d");
if (a == true && b == true && c == true) {
return true;
} else {
return false;
}
}
private boolean doesRowTextContain(int index, String expectedString) {
By spanSelector = By.xpath(".//span[#class='da']"); //the dot . reduces the scope of the element. Instead of searching through all the elements in source, we'll reduce the scope to parent element
List<WebElement> dataRows = driver.findElements(By.xpath("//tr[#data-testid='row']//td[#class='kor']"));
return dataRows.get(index).findElement(spanSelector).getText().contains(expectedString);
}
One more thing is - you don't have to compare a, b or c with true as it's default expected value in if statement.
if (a && b && c) {
return true;
} else {
return false;
}
Or even
return a && b && c :)
Final methods could look like this:
public boolean VerifyKORSecDispaly() {
return doesRowTextContain(0, "d") && doesRowTextContain(1, "d") && doesRowTextContain(2, "d");
}
private boolean doesRowTextContain(int index, String expectedString) {
By spanSelector = By.xpath(".//span[#class='da']"); //the dot . reduces the scope of the element. Instead of searching through all the elements in source, we'll reduce the scope to parent element
List<WebElement> dataRows = driver.findElements(By.xpath("//tr[#data-testid='row']//td[#class='kor']"));
return dataRows.get(index).findElement(spanSelector).getText().contains(expectedString);
}
I have below code snippet, Is any other efficient way exists to achieve the same in java 8. I have tried lambda expression but throws error when i assign some variable inside lambda function.
public boolean countUsers(UserDetais details){
List<SystemProfile> systemProfileDataList = getSystemProfileData();
int userCountForService = service.getUserCountByService(details.id);
int vpcUsersCount=0;
int internetUsersCount=0;
if (systemProfileDataList != null) {
SystemProfile sysProfile;
Iterator profileItr = systemProfileDataList.iterator();
while (profileItr.hasNext()) {
SystemProfile sysProfile = (SystemProfile) profileItr.next();
if(sysProfile.getName().equalsIgnoreCase(IPConstants.DEFAULT_MAX_USERS)) {
vpcUsersCount = Integer.parseInt(sysProfile.getValue());
if (userCountForService > vpcUsersCount) {
maxUserFlag = true;
break;
}
}else if(sysProfile.getName().equalsIgnoreCase(IPConstants.DEAULT_MAX_USERS_WITH_INTERNET)) {
internetUsersCount = Integer.parseInt(sysProfile.getValue());
if (userCountForService > internetUsersCount) {
maxUserFlag = true;
break;
}
}
}
}
I think this should work :
boolean tooManyUsers = getSystemProfileData().stream()
.anyMatch((SystemProfile s) ->
s.getName().equalsIgnoreCase(IPConstants.DEFAULT_MAX_USERS)
&& Integer.parseInt(sysProfile.getValue()) < userCountForService
||
s.getName().equalsIgnoreCase(IPConstants.DEAULT_MAX_USERS_WITH_INTERNET)
&& Integer.parseInt(sysProfile.getValue()) < internetUsersCount
);
I have two Lists. One I created from Database and one from Csv file. Now I want to collect records in a list that contain both in database and csv file. I wrote code like below
BiPredicate<Trainee, Trainee> sameTrainee = (dbTrainee, csvTrainee) -> {
String dbTraineeFirstName = dbTrainee.getFirstName();
String dbTraineeLastName = dbTrainee.getLastName();
String dbTraineeEmail = dbTrainee.getEmail();
LocalDateTime dbTraineeCompletionDate = dbTrainee.getSessionDateTime();
String text = dbTraineeCompletionDate.format(DATE_TIME_FORMATTER);
LocalDateTime dbTraineeSessionDateTime = LocalDateTime.parse(text);
String dbTraineePhoneNumber = dbTrainee.getPhoneNumber();
String dbTraineeSsn = dbTrainee.getSocialSecurityLastFour();
String dbTraineeStreetOne = dbTrainee.getStreetOne();
String dbTraineeCity = dbTrainee.getCity();
String csvTraineeFirstName = csvTrainee.getFirstName();
String csvTraineeLastName = csvTrainee.getLastName();
String csvTraineeEmail = csvTrainee.getEmail();
LocalDateTime csvTraineeSessionDateTime = csvTrainee.getSessionDateTime();
String csvTraineePhoneNumber = csvTrainee.getPhoneNumber();
String csvTraineeSsn = csvTrainee.getSocialSecurityLastFour();
String csvTraineeStreetOne = csvTrainee.getStreetOne();
String csvTraineeCity = csvTrainee.getCity();
int dbTraineeSsnLength = dbTraineeSsn.length();
int csvTraineeSsnLength = csvTraineeSsn.length();
if (dbTraineeSsnLength != csvTraineeSsnLength) {
if (dbTraineeSsnLength == 4 && dbTraineeSsn.startsWith("0")) {
String dbTraineeSsnLast3Digits = dbTraineeSsn.substring(dbTraineeSsn.length() - 3);
if (csvTraineeSsnLength == 3 && csvTraineeSsn.endsWith(dbTraineeSsnLast3Digits)) {
csvTraineeSsn = "0" + csvTraineeSsn;
}
}
}
return dbTraineeFirstName.equals(csvTraineeFirstName)
&& dbTraineeLastName.equals(csvTraineeLastName)
&& dbTraineeEmail.equals(csvTraineeEmail)
&& dbTraineeSessionDateTime.equals(csvTraineeSessionDateTime)
&& dbTraineePhoneNumber.equals(csvTraineePhoneNumber)
&& dbTraineeSsn.equals(csvTraineeSsn)
&& dbTraineeStreetOne.equals(csvTraineeStreetOne)
&& dbTraineeCity.equals(csvTraineeCity);
};
and called it like
List<Trainee> foundInBothList = dbMonthlyTraineeList.stream()
.filter(dbTrainee -> csvTraineeList.stream()
.anyMatch(csvTrainee -> {
return sameTrainee.test(dbTrainee, csvTrainee);
})
).collect(Collectors.toList());
List<Trainee> notInFileList = dbMonthlyTraineeList.stream()
.filter(dbTrainee -> csvTraineeList.stream()
.noneMatch(csvTrainee -> {
return sameTrainee.test(dbTrainee, csvTrainee);
})
).collect(Collectors.toList());
It works fine. But as my BiPredicate is getting long and untidy. So I made a class and collect all the predicates in a Collection like below
public class PlcbMonthlyReportStatisticsBiPredicates {
public static BiPredicate<Trainee, Trainee> isValidFirstName() {
return (dbTrainee, csvTrainee) -> {
String dbTraineeFirstName = dbTrainee.getFirstName();
String csvTraineeFirstName = csvTrainee.getFirstName();
return dbTraineeFirstName.equals(csvTraineeFirstName);
};
}
public static BiPredicate<Trainee, Trainee> isValidSsn() {
return (dbTrainee, csvTrainee) -> {
String dbTraineeSsn = dbTrainee.getSocialSecurityLastFour();
String csvTraineeSsn = csvTrainee.getSocialSecurityLastFour();
...
return dbTraineeSsn.equals(csvTraineeSsn);
};
}
....
public static List<BiPredicate<Trainee, Trainee>> getAllBiPredicates() {
List<BiPredicate<Trainee, Trainee>> allPredicates = Arrays.asList(
isValidFirstName(),
isValidSsn(),
...
);
return allPredicates;
}
}
Now I Collect all the predicates but how can I apply these predicates in my anyMatch() and noneMatch(). I tried this but of-cources getting error
List<Trainee> foundInBothList1 = dbMonthlyTraineeList.stream()
.filter(dbTrainee -> csvTraineeList.stream()
.anyMatch(csvTrainee -> {
List<BiPredicate<Trainee, Trainee>> allBiPredicates = getAllBiPredicates();
return allBiPredicates.stream().reduce(BiPredicate::and).orElse((x,y)->true); //error
})
).collect(Collectors.toList());
How can I apply this. Is my approach is right?
**Edit
#Entity
public class Trainee {
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
private LocalDateTime sessionDateTime;
private String firstName;
....
#Override
public boolean equals(Object otherObject) {
// Are the same?
if (this == otherObject) {
return true;
}
// Is otherObject a null reference?
if (otherObject == null) {
return false;
}
// Do they belong to the same class?
if (this.getClass() != otherObject.getClass()) {
return false;
}
// Get the reference of otherObject in a otherTrainee variable
Trainee otherTrainee = (Trainee)otherObject;
LocalDateTime dbTraineeCompletionDate = this.getSessionDateTime();
String text = dbTraineeCompletionDate.format(DATE_TIME_FORMATTER);
LocalDateTime dbTraineeSessionDateTime = LocalDateTime.parse(text);
String dbTraineeSsn = this.socialSecurityLastFour;
String csvTraineeSsn = otherTrainee.getSocialSecurityLastFour();
int dbTraineeSsnLength = dbTraineeSsn.length();
int csvTraineeSsnLength = csvTraineeSsn.length();
if (dbTraineeSsnLength != csvTraineeSsnLength) {
if (dbTraineeSsnLength == 4 && dbTraineeSsn.startsWith("0")) {
String dbTraineeSsnLast3Digits = dbTraineeSsn.substring(dbTraineeSsn.length() - 3);
if (csvTraineeSsnLength == 3 && csvTraineeSsn.endsWith(dbTraineeSsnLast3Digits)) {
csvTraineeSsn = "0" + csvTraineeSsn;
}
}
}
boolean isEqual = (this.firstName.equals(otherTrainee.firstName)
&& this.lastName.equals(otherTrainee.lastName)
&& this.email.equals(otherTrainee.email)
&& dbTraineeSessionDateTime.equals(otherTrainee.sessionDateTime)
&& this.phoneNumber.equals(otherTrainee.phoneNumber)
&& dbTraineeSsn.equals(csvTraineeSsn)
&& this.streetOne.equals(otherTrainee.streetOne)
&& this.city.equals(otherTrainee.city)
);
return isEqual;
}
#Override
public int hashCode() {
int hash = 37;
int code = 0;
code = (firstName == null ? 0 : firstName.hashCode());
hash = hash * 59 + code;
code = (lastName == null ? 0 : lastName.hashCode());
hash = hash * 59 + code;
code = (email == null ? 0 : email.hashCode());
hash = hash * 59 + code;
code = (sessionDateTime == null ? 0 : sessionDateTime.hashCode());
hash = hash * 59 + code;
code = (phoneNumber == null ? 0 : phoneNumber.hashCode());
hash = hash * 59 + code;
code = (socialSecurityLastFour == null ? 0 : socialSecurityLastFour.hashCode());
hash = hash * 59 + code;
code = (streetOne == null ? 0 : streetOne.hashCode());
hash = hash * 59 + code;
code = (city == null ? 0 : city.hashCode());
hash = hash * 59 + code;
return hash;
}
}
Edit 2 (After overridng hascode() and equals())
-------------------------------------------------
Found in both:
List<Trainee> foundInBothList1 = dbMonthlyTraineeList.stream()
.filter(dbTrainee -> csvTraineeList.stream()
.anyMatch(csvTrainee -> {
return allBiPredicates.stream().reduce(BiPredicate::and).orElse((x,y)->true).test(dbTrainee, csvTrainee);
})
).collect(Collectors.toList());
List<Trainee> foundInBothList = new ArrayList<>(dbMonthlyTraineeList);
//foundInBothList.retainAll(new HashSet<>(csvTraineeList));
foundInBothList.retainAll(csvTraineeList);
Found in database but not in CSV
List<Trainee> notInCsvFileList1 = dbMonthlyTraineeList.stream()
.filter(dbTrainee -> csvTraineeList.stream()
.noneMatch(csvTrainee -> {
return allBiPredicates.stream().reduce(BiPredicate::and).orElse((x,y)->true).test(dbTrainee, csvTrainee);
})
).collect(Collectors.toList());
//find out that elements of dbMonthlyTraineeList which is not present in arraylist(csvTraineeList).
List<Trainee> notInCsvFileList = new ArrayList<>(dbMonthlyTraineeList);
notInCsvFileList.removeAll(csvTraineeList);
It looks like you are over-thinking this. Why not just override equals with your sameTrainee bi-predicate code? (Don't forget to override hashCode also).
After you do this, you can keep the Trainees that are in both lists using:
Set<Trainee> foundInBothList = new HashSet<>(dbMonthlyTraineeList);
foundInBothList.retainAll(new HashSet<>(csvTraineeList));
This solution is O(n) and so it will perform a lot better than your solution, which is O(n²). This is because the contains operation is constant-time on a Set.
But if you really want your code to compile, you just need to call the test method where you have the error:
return allBiPredicates.stream().reduce(BiPredicate::and)
.orElse((x,y)->true)
.test(dbTrainee, csvTrainee);
I need to check if all values in a map are equal. I have a method to perform this task but would like to use a library or native methods. Limitations: Java 5 + Apache Commons libraries.
public static boolean isUnique(Map<Dboid,?> aMap){
boolean isUnique = true;
Object currValue = null;
int iteration = 0;
Iterator<?> it = aMap.entrySet().iterator();
while(it.hasNext() && isUnique){
iteration++;
Object value = it.next();
if(iteration > 1){
if (value != null && currValue == null ||
value == null && currValue != null ||
value != null && currValue != null & !value.equals(currValue)) {
isUnique = false;
}
}
currValue = value;
}
return isUnique;
}
What about this something like this:
Set<String> values = new HashSet<String>(aMap.values());
boolean isUnique = values.size() == 1;
how about
return (new HashSet(aMap.values()).size() == 1)
I know the original questions asks for solutions in Java 5, but in case someone else searching for an answer to this question is not limited to Java 5 here is a Java 8 approach.
return aMap.values().stream().distinct().limit(2).count() < 2
You could store the values in a Bidirectional Map and always have this property.
public static boolean isUnique(Map<Dboid,?> aMap) {
Set<Object> values = new HashSet<Object>();
for (Map.Entry<Dboid,?> entry : aMap.entrySet()) {
if (!values.isEmpty() && values.add(entry.getValue())) {
return false;
}
}
return true;
}
This solution has the advantage to offer a memory-saving short cut if there are many differences in the map. For the special case of an empty Map you might choose false as return value, change it appropriately for your purpose.
Or even better without a Set (if your Map does not contain null-values):
public static boolean isUnique(Map<Dboid,?> aMap) {
Object value = null;
for (Object entry : aMap.values()) {
if (value == null) {
value = entry;
} else if (!value.equals(entry)) {
return false;
}
}
return true;
}
As my comment above:
//think in a more proper name isAllValuesAreUnique for example
public static boolean isUnique(Map<Dboid,?> aMap){
if(aMap == null)
return true; // or throw IlegalArgumentException()
Collection<?> c = aMap.getValues();
return new HashSet<>(c).size() <= 1;
}
Are there any java libraries or techniques to parsing boolean expressions piecemeal?
What I mean is given an expression like this:
T && ( F || ( F && T ) )
It could be broken down into a expression tree to show which token caused the 'F' value, like so (maybe something like this):
T && <- rhs false
( F || <- rhs false
( F && T ) <- eval, false
)
I am trying to communicate boolean expression evaluations to non-programmers. I have poked around with Anlr, but I couldn't get it to do much (it seems to have a bit of a learning curve).
I'm not opposed to writing it myself, but I'd rather not reinvent the wheel.
You could do this with MVEL or JUEL. Both are expression language libraries, examples below are using MVEL.
Example:
System.out.println(MVEL.eval("true && ( false || ( false && true ) )"));
Prints:
false
If you literally want to use 'T' and 'F' you can do this:
Map<String, Object> context = new java.util.HashMap<String, Object>();
context.put("T", true);
context.put("F", false);
System.out.println(MVEL.eval("T && ( F || ( F && T ) )", context));
Prints:
false
I've coded this using Javaluator.
It's not exactly the output you are looking for, but I think it could be a start point.
package test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import net.astesana.javaluator.*;
public class TreeBooleanEvaluator extends AbstractEvaluator<String> {
/** The logical AND operator.*/
final static Operator AND = new Operator("&&", 2, Operator.Associativity.LEFT, 2);
/** The logical OR operator.*/
final static Operator OR = new Operator("||", 2, Operator.Associativity.LEFT, 1);
private static final Parameters PARAMETERS;
static {
// Create the evaluator's parameters
PARAMETERS = new Parameters();
// Add the supported operators
PARAMETERS.add(AND);
PARAMETERS.add(OR);
// Add the parentheses
PARAMETERS.addExpressionBracket(BracketPair.PARENTHESES);
}
public TreeBooleanEvaluator() {
super(PARAMETERS);
}
#Override
protected String toValue(String literal, Object evaluationContext) {
return literal;
}
private boolean getValue(String literal) {
if ("T".equals(literal) || literal.endsWith("=true")) return true;
else if ("F".equals(literal) || literal.endsWith("=false")) return false;
throw new IllegalArgumentException("Unknown literal : "+literal);
}
#Override
protected String evaluate(Operator operator, Iterator<String> operands,
Object evaluationContext) {
List<String> tree = (List<String>) evaluationContext;
String o1 = operands.next();
String o2 = operands.next();
Boolean result;
if (operator == OR) {
result = getValue(o1) || getValue(o2);
} else if (operator == AND) {
result = getValue(o1) && getValue(o2);
} else {
throw new IllegalArgumentException();
}
String eval = "("+o1+" "+operator.getSymbol()+" "+o2+")="+result;
tree.add(eval);
return eval;
}
public static void main(String[] args) {
TreeBooleanEvaluator evaluator = new TreeBooleanEvaluator();
doIt(evaluator, "T && ( F || ( F && T ) )");
doIt(evaluator, "(T && T) || ( F && T )");
}
private static void doIt(TreeBooleanEvaluator evaluator, String expression) {
List<String> sequence = new ArrayList<String>();
evaluator.evaluate(expression, sequence);
System.out.println ("Evaluation sequence for :"+expression);
for (String string : sequence) {
System.out.println (string);
}
System.out.println ();
}
}
Here is the ouput:
Evaluation sequence for :T && ( F || ( F && T ) )
(F && T)=false
(F || (F && T)=false)=false
(T && (F || (F && T)=false)=false)=false
Evaluation sequence for :(T && T) || ( F && T )
(T && T)=true
(F && T)=false
((T && T)=true || (F && T)=false)=true
I recently put together a library in Java specifically to manipulate boolean expressions: jbool_expressions.
It includes a tool too parse expressions out of string input:
Expression<String> expr = ExprParser.parse("( ( (! C) | C) & A & B)")
You can also do some fairly simple simplification:
Expression<String> simplified = RuleSet.simplify(expr);
System.out.println(expr);
gives
(A & B)
If you wanted to step through the assignment then, you could assign values one by one. For the example here,
Expression<String> halfAssigned = RuleSet.assign(simplified, Collections.singletonMap("A", true));
System.out.println(halfAssigned);
shows
B
and you could resolve it by assigning B.
Expression<String> resolved = RuleSet.assign(halfAssigned, Collections.singletonMap("B", true));
System.out.println(resolved);
shows
true
Not 100% what you were asking for, but hope it helps.
Check out BeanShell. It has expression parsing that accepts Java-like syntax.
EDIT: Unless you're trying to actually parse T && F literally, though you could do this in BeanShell using the literals true and false.
Try this.
static boolean parseBooleanExpression(String s) {
return new Object() {
int length = s.length(), index = 0;
boolean match(String expect) {
while (index < length && Character.isWhitespace(s.charAt(index)))
++index;
if (index >= length)
return false;
if (s.startsWith(expect, index)) {
index += expect.length();
return true;
}
return false;
}
boolean element() {
if (match("T"))
return true;
else if (match("F"))
return false;
else if (match("(")) {
boolean result = expression();
if (!match(")"))
throw new RuntimeException("')' expected");
return result;
} else
throw new RuntimeException("unknown token");
}
boolean term() {
if (match("!"))
return !element();
else
return element();
}
boolean factor() {
boolean result = term();
while (match("&&"))
result &= term();
return result;
}
boolean expression() {
boolean result = factor();
while (match("||"))
result |= factor();
return result;
}
boolean parse() {
boolean result = expression();
if (index < length)
throw new RuntimeException(
"extra string '" + s.substring(index) + "'");
return result;
}
}.parse();
}
And
public static void main(String[] args) {
String s = "T && ( F || ( F && T ) )";
boolean result = parseBooleanExpression(s);
System.out.println(result);
}
output:
false
The syntax is
expression = factor { "||" factor }
factor = term { "&&" term }
term = [ "!" ] element
element = "T" | "F" | "(" expression ")"
mXparser handles Boolean operators - please find few examples
Example 1:
import org.mariuszgromada.math.mxparser.*;
...
...
Expression e = new Expression("1 && (0 || (0 && 1))");
System.out.println(e.getExpressionString() + " = " + e.calculate());
Result 1:
1 && (0 || (0 && 1)) = 0.0
Example 2:
import org.mariuszgromada.math.mxparser.*;
...
...
Constant T = new Constant("T = 1");
Constant F = new Constant("F = 0");
Expression e = new Expression("T && (F || (F && T))", T, F);
System.out.println(e.getExpressionString() + " = " + e.calculate());
Result 2:
T && (F || (F && T)) = 0.0
For more details please follow mXparser tutorial.
Best regards