I have multiple conditions to check as shown below,
if(pouch.getStatus().equals("Finalized") || pouch.getStatus().equals("Ready")
|| pouch.getStatus().equals("Checkout") || pouch.getStatus().equals("Confirmed")
|| pouch.getStatus().equals("Book") || pouch.getStatus().equals("Started")
|| pouch.getStatus().equals("Inital") || pouch.getStatus().equals("Close")) {
// Body Implementation
}
Is there any easy way to check above conditions similar like SQL INcondition, so that code look simpler?
Let's take a look about SQL in features
SQL WHERE IN returns values that match values in a list
So I would use a collection, which implements from Collection<E> and had contains method, make the if statement simpler.
contains(Object o) Returns true if this set contains the specified element.
contains effect is very similar to SQL in.
1.add your multiple conditions in the collection, which implements from Collection<E>
Set<String> dict = new HashSet<String>();
dict.add("Finalized");
dict.add("Ready");
dict.add("Checkout");
dict.add("Confirmed");
dict.add("Book");
dict.add("Started");
dict.add("Inital");
dict.add("Close");
2.using contains to check input value whether exist in the collection.
if (dict.contains(pouch.getStatus()))
{
// do your logic
}
You can use the method matches which is available in String class,
if(pouch.getStatus().matches("Finalized|Ready|Checkout|Confirmed|Book|Started|Inital|Close")){
//your implementation goes here
}
List<String> listOfInputs = new ArrayList<String>();
// add elements in listOfInputs...
boolean isAvailable = listOfInputs.contains(pouch.getStatus());
SQL IN might return more than one result, but in your question, if one condition is satisfied the operation will terminate and return.
You can create an enum to hold all your conditions as shown below.
Assuming your Pouch class is this.
public class Pouch {
private final String status;
public Pouch(final String status) {
this.status = status;
}
public String getStatus() {
return status;
}
}
Here is your enum with the pouch status.
public enum PouchEnum {
Finalized, Ready, Checkout, Confirmed, Book, Started, Inital, Close
}
and check your condition as shown below.
if (PouchEnum.valueOf(pouch.getStatus()) != null) {
// Do some stuff
}
To make it cleaner you can use EnumUtils from apache commons-lang3 this make your code checking more cleaner as shown below.
if (EnumUtils.isValidEnum(PouchEnum.class, pouch.getStatus())) {
// Do some stuff
}
I hope this will help your code to be cleaner.
You can create custom function:
static boolean inCondition(String var, String... ins) {
for (String in : ins) {
if (in.equals(var)) return true;
}
return false;
}
and then use it in this way:
public static void main(String[] args) {
String pouch = "Ready";
if (inCondition(pouch, "Finalized", "Ready", "Checkout" ... )) {
// do something
}
}
Below snippet might help you.
String status = "COMPLETED";
List<String> statusList = new ArrayList<>(Arrays.asList("COMPLETED","INPROGRESS"));
if(statusList.contains(status)){
// do your stuff
}
Using Arrays.asList and then use contains might be the best way at least on my case.
if(Arrays.asList("Finalized", "Ready", "Checkout", "Confirmed",
"Book", "Started", "Inital", "Close").contains(pouch.getStatus())) {
// Body
}
I think if you use the "switch" conditional, the code reads better:
switch (pouch.getStatus()) {
case "Finalized":
case "Ready":
case "Checkout":
case "Confirmed":
case "Book":
case "Started":
case "Inital":
case "Close":
// your code
break;
}
For this particular scenario, I think it's a good candidate for a simple enum like this:
public enum PouchStatus {
FINALIZED, READY, CHECKOUT, CONFIRMED, BOOK, STARTED, INITIAL, CLOSE
}
Usage:
if(PouchStatus.valueOf(pouch.getStatus().toUpperCase()) != null) {
}
You can also move this string sanitizing logic inside a static method in the enum, which would look like this:
public enum PouchStatus {
FINALIZED, READY, CHECKOUT, CONFIRMED, BOOK, STARTED, INITIAL, CLOSE
public static PouchStatus fromDescription(String desc) {
return Arrays.stream(PouchStatus.values()).filter(e -> e.name().equalsIgnoreCase(desc)).findFirst().orElse(null);
}
}
Usage:
if (PouchStatus.fromDescription(pouch.getStatus()) != null) {
}
As a final note, if the Pouch object comes from ORM (e.g.: hibernate/jpa) you can just map these values to the according enum elements right in the entity mapping (pouc.getStatus() would already return a PouchStatus object instead of a String).
Here is full example
public class InConditionJava {
public static void main(String[] args) {
// TODO Auto-generated method stub
String[] arr = { "Finalized", "Ready", "Checkout" };
checkData(arr);
}
private static void checkData(String[] arr) {
Set<String> names = new HashSet<String>(Arrays.asList(arr));
System.out.println("AS Checkout is there in our arr is should return True>>" + names.contains("Checkout")); // true
System.out.println(names.contains("Book")); // false
}
}
Here is another way of initializing List in one line with all statuses, and then checking if the list contains the given status.
// Java 9 way of initializing List with one line
List<String> statuses = List.of("Finalized", "Ready", "Checkout", "Confirmed",
"Book", "Started", "Inital", "Close");
if (statuses.contains(pouch.getStatus())) {
// Body
}
You can create an array of all status, then check if pouch.getStatus() in in that list or not?
public String[] statusArray = new String[]{ "Finalized", "Ready","Checkout","Confirmed", "Book", "Started", "Inital", "Close"};
if( Arrays.asList(statusArray).contains(pouch.getStatus())){
//do something
}
There are already plenty of options here, but you could also use Stream for this task, if the version of the JDK you are using is >= 8:
String status = pouch.getStatus();
if (Stream.of(
"Finalized",
"Ready",
"Checkout",
"Confirmed",
"Book",
"Started",
"Inital",
"Close")
.anyMatch(status::equals)) {
// Body
}
The downside of this method, compared to Collection#contains, is that you must make sure that pouch.getStatus() is not null, otherwise you will get a NullPointerException.
Related
The code below compiles and does its job, however lets say I needed to added another 100 if statements that uses a reference. Whats the most efficient way to write multiple if statements?
public String getForceDetails(String ref) {
if (ref.equals("IW1")) {
setupForces();
return (ForceDetails.get(0).toString());
} else if (ref.equals("SS2")) {
setupForces();
return (ForceDetails.get(1).toString());
} else if (ref.equals("WB3")) {
setupForces();
return (ForceDetails.get(2).toString());
} else if (ref.equals("IW4")) {
setupForces();
return (ForceDetails.get(3).toString());
} else if (ref.equals("WB5")) {
setupForces();
return (ForceDetails.get(4).toString());
} else if (ref.equals("SS6")) {
setupForces();
return (ForceDetails.get(5).toString());
} else if (ref.equals("SS7")) {
setupForces();
return (ForceDetails.get(6).toString());
} else if (ref.equals("WB9")) {
setupForces();
return (ForceDetails.get(7).toString());
} else if (ref.equals("IW10")) {
setupForces();
return (ForceDetails.get(8).toString());
} else {
return "\nNo such force";
}
}
private void setupForces()
{
ForceDetails.add(new starShip("IW1","Twisters",200,200,ForceState.DOCKED,10,0,0,false));
ForceDetails.add(new starShip("SS2","Enterprise",300,200,ForceState.DOCKED,0,10,20,false));
ForceDetails.add(new starShip("WB3","Droop",300,100,ForceState.DOCKED,0,0,0,false));
ForceDetails.add(new starShip("IW4","Wingers",200,400,ForceState.DOCKED,20,0,0,false));
ForceDetails.add(new starShip("WB5","Hang",400,300,ForceState.DOCKED,0,0,0,true));
ForceDetails.add(new starShip("SS6","Voyager",450,200,ForceState.DOCKED,0,15,10,false));
ForceDetails.add(new starShip("SS7","Explorer",120, 65,ForceState.DOCKED,0,4,5,false));
ForceDetails.add(new starShip("WB9","Hover",300,400,ForceState.DOCKED,0,0,0,false));
ForceDetails.add(new starShip("IW10","Flyers",200,100,ForceState.DOCKED,5,0,0,false));
}
The obvious choice would be a switch statement over ref:
switch (ref) {
case "IW1":
setupForces();
return (ForceDetails.get(0).toString());
break;
case "SS2":
setupForces();
return (ForceDetails.get(1).toString());
break;
// etc.
}
If the code to execute always looks the like this (calling setupForces() and getting the n-th element of ForceDetails) you could also use a map that lets you retrieve n (Map<String, Integer>) which you populate with key-value-pairs like "IW1"->0 and "SS2"->1 etc.
The map solution also has the charme that you do not need to repeat the code that is basically equal for all cases which would be rather inconvenient if you have to change this later.
Well there is no inbuilt solution to that. What you can do is create a Map of condition -> result and return the value to the key.
Map<String, String> mapCondToRes = new HashMap<>();
public String getForceDetails(String ref) {
setupForces();
return mapCondToRes.get(ref);
}
You can check for validations and put more conditions very easily and elegantly.
In the existing code, each invocation of getForceDetails with a valid ref causes adding of 9 entries to a collection of starships ForceDetails. It is doubtful that this behaviour is intended, possibly a lazy initialization of ForceDetails was implied.
Next, to get rid of the multiple if statements using of the map is definitely more preferable than converting into switch statement and copying the same multiple calls to setupForces(). It could make sense to create a map Map<String, starship> instead of the list and populate it in setupForces (so there's no need to have a separate map of references to the index in the list):
Map<String, starShip> forces = new HashMap<>();
private void setupForces() {
forces.put("IW1", new starShip("IW1","Twisters",200,200,ForceState.DOCKED,10,0,0,false));
forces.put("SS2", new starShip("SS2","Enterprise",300,200,ForceState.DOCKED,0,10,20,false));
// ... add other starships mapped by their ids
}
public String getForceDetails(String ref) {
if (forces.isEmpty()) {
setupForces();
}
return Optional.ofNullable(forces.get(ref))
.map(starShip::toString)
.orElse("No such force found");
}
Use a java stream, you should read about them, you'll find it useful later as you progress on Java.
For the following code, I assume you have a getter for your "key" values inside your starShip class ("IW1", "SS2", "WB3"...).
This code also assumes that you cannot change your current List approach, If you can, a Map would be a even better.
private static final String NO_FORCE = "\nNo such force";
public String getForceDetails(String ref) {
String result = ForceDetails.stream() // <-- It's even faster if you use `parallelStream` however is known to have non-thread-safe issues
.filter(starShipItem -> Objects.equals(starShipItem.getKey(), ref))
.map(String::valueOf).findFirst()
.orElse(NO_FORCE)
;
if (NO_FORCE.equals(result)) {
return NO_FORCE;
}
setupForces();
return result;
}
Also, I recommend you to take a look at hackerrank challenges, you'll learn a lot more there.
I understand you can't return from a ifPresent() so this example does not work:
public boolean checkSomethingIfPresent() {
mightReturnAString().ifPresent((item) -> {
if (item.equals("something")) {
// Do some other stuff like use "something" in API calls
return true; // Does not compile
}
});
return false;
}
Where mightReturnAString() could return a valid string or an empty optional. What I have done that works is:
public boolean checkSomethingIsPresent() {
Optional<String> result = mightReturnAString();
if (result.isPresent()) {
String item = result.get();
if (item.equals("something") {
// Do some other stuff like use "something" in API calls
return true;
}
}
return false;
}
which is longer and does not feel much different to just checking for nulls in the first place. I feel like there must be a more succinct way using Optional.
I think all you're looking for is simply filter and check for the presence then:
return result.filter(a -> a.equals("something")).isPresent();
How about mapping to a boolean?
public boolean checkSomethingIfPresent() {
return mightReturnAString().map(item -> {
if (item.equals("something")) {
// Do some other stuff like use "something" in API calls
return true; // Does not compile
}
return false; // or null
}).orElse(false);
}
While #nullpointer and #Ravindra showed how to merge the Optional with another condition, you'll have to do a bit more to be able to call APIs and do other stuff as you asked in the question. The following looks quite readable and concise in my opinion:
private static boolean checkSomethingIfPresent() {
Optional<String> str = mightReturnAString();
if (str.filter(s -> s.equals("something")).isPresent()) {
//call APIs here using str.get()
return true;
}
return false;
}
A better design would be to chain methods:
private static void checkSomethingIfPresent() {
mightReturnFilteredString().ifPresent(s -> {
//call APIs here
});
}
private static Optional<String> mightReturnFilteredString() {
return mightReturnAString().filter(s -> s.equals("something"));
}
private static Optional<String> mightReturnAString() {
return Optional.of("something");
}
The ideal solution is “command-query separation”: Make one method (command) for doing something with the string if it is present. And another method (query) to tell you whether it was there.
However, we don’t live an ideal world, and perfect solutions are never possible. If in your situation you cannot separate command and query, my taste is for the idea already presented by shmosel: map to a boolean. As a detail I would use filter rather than the inner if statement:
public boolean checkSomethingIfPresent() {
return mightReturnAString().filter(item -> item.equals("something"))
.map(item -> {
// Do some other stuff like use "something" in API calls
return true; // (compiles)
})
.orElse(false);
}
What I don’t like about it is that the call chain has a side effect, which is not normally expected except from ifPresent and ifPresentOrElse (and orElseThrow, of course).
If we insist on using ifPresent to make the side effect clearer, that is possible:
AtomicBoolean result = new AtomicBoolean(false);
mightReturnAString().filter(item -> item.equals("something"))
.ifPresent(item -> {
// Do some other stuff like use "something" in API calls
result.set(true);
});
return result.get();
I use AtomicBoolean as a container for the result since we would not be allowed to assign to a primitive boolean from within the lambda. We don’t need its atomicity, but it doesn’t harm either.
Link: Command–query separation on Wikipedia
By the way if you really want to get value from Optional, use:
Optional<User> user = service.getCurrentUset();
return user.map(User::getId);
In my code I write a "Project" object that can contains an Arraylist of "Requirement" objects. I want to write a function that can calculate the status of my Project objects :
1) "Status" can only have 3 values : "todo", "in progress" and "done"
2) If the status of ONE requirement (in the arraylist) is "todo", the final status of the project is "todo".
3) If the status of ALL requirements is "in progress", the status of the project will be "in progress". The same thing for the last status (done).
4) If some requirements have "in progress" status while other have "done" status, the final status of the project will be "in progress". But I don't how can I write this case in the function.
I search a clean way to code this. I'm sure it's easy in Java but I'm newbie in Java and I don't feel comfortable with ArrayList.
I tried this :
#Override
public String getStatus(Project project){
Iterator<Requirement> it = project.listRequirement.iterator();
while (it.hasNext()) {
Requirement s = it.next();
if (s.getStatus()=="TODO") return "TODO";
//I don't know how I can write the others lines for the two others status
}
}
Can you help me please to complete my function? Thanks
Your comparison logic in if (s.getStatus()=="TODO") is incorrect as you are using == to compare the Strings. You should be using equals() or equalsIgnoreCase() instead.
You can use a boolean to track the statuses. If none of your conditions gets fulfilled then you can return null from the function and handle it appropriately in your code.
Here is the corrected snippet:
#Override
public String getStatus(Project project) {
/* Create Final Strings */
final String TODO = "TODO";
final String INP = "In Progress";
final String DONE = "Done";
/* Boolean Flag */
boolean flag = false;
/* Comparison Logic */
Iterator<Requirement> it = project.listRequirement.iterator();
while (it.hasNext()) {
Requirement s = it.next();
if (TODO.equalsIgnoreCase(s.getStatus())) {
return TODO;
} else if (INP.equalsIgnoreCase(s.getStatus())) {
flag = true;
}
}
/* Return Done */
if(flag) return INP;
else return DONE;
}
Also, you can use if-else or switch() to do the comparisons.
You can use the List method "contains" to check if a list contains a certain element.
But your logic seems incomplete: What about if the list contains status of both "DONE" and "in progess" (And no "todo")? You never specified what should be returned in that case.
To check if a List only contains status of one type, I would copy the list to a Set (A Collections that doesn't allow duplicates) and then check if that sets size is 1
so maybe something like
if(project.listRequirement.contains("TODO")) {
return "TODO";
} else if(project.listRequirement.contains("INPROGRESS") && new HashSet<String>(project.listRequirement).size()==1) {
return "INPROGRESS";
} else if(project.listRequirement.contains("DONE") && new HashSet<String>(project.listRequirement).size()==1) {
return "DONE";
} else {
// These are the cases your logic doesn't cover yet.....
}
Edit:
#PyThon I forget that. In this case, the status of the progress will be "in progress" (since the entire project is not completly done). But I don't have an idea how to program that...
Okay, so if the list looks like this ("DONE", "DONE", "INPROGRESS") the result is supposed to be "INPROGRESS"?
In that case my edited code from above:
if(project.listRequirement.contains("TODO")) {
// list contains a todo
return "TODO";
} else if(project.listRequirement.contains("DONE") && new HashSet<String>(project.listRequirement).size()==1) {
// list contains no todo, and only "done" as only status
return "DONE";
} else if(project.listRequirement.contains("INPROGRESS")) {
// list contains no todo, but does contain in progress
return "INPROGRESS";
} else {
// this should never happen!
throw new IllegalStateException();
}
If you use Java 8
public static String getStatus(List<Requirement> requirement) {
if (requirement.stream().anyMatch(r -> r.getStatus().equals("TODO"))) {
return "TODO";
} else if (requirement.stream().allMatch(r -> r.getStatus().equals("DONE"))) {
return "DONE";
} else {
return "IN PROGRESS";
}
}
If there is any TODO then it is TODO
If all are DONE, then it is DONE
If there are no TODO and not all are done, then some or all must be IN PROGRESS
I am getting a warning that watchStore.contains(s) is a suspicious call to java.util.Collection#contains. How can I fix it? I want to use contains() to find a particular object with the matching serial number.
public Watch findWatchBySerialNumber(long srch) {
long s = srch;
Watch watch = null;
for(int i = 0; i < watchStore.size(); i++) {
watch = watchStore.get(i);
if(watchStore.contains(s)) {
System.out.print("item found");
return watch;
}
}
System.out.print("item not found");
return null; // watch is not found.
}
Presuming that Watch is the class, watchStore is a List<Watch>, and that a field serialNo exists on Watch...
public Optional<Watch> findWatchBySerialNumber(long serial) {
return watchStore.stream()
.filter(w -> w.getSerialNo() == serial)
.findFirst();
}
If you're not using Java 8, the code is close, but a bit more dangerous since you have the chance to return null. If you can use Guava's Optional, that'd be a better choice here.
public Watch findWatchBySerialNumber(long serial) {
for(Watch w : watchStore) {
if(w.getSerialNo() == serial) {
return w;
}
}
return null;
}
Your contains isn't going to work since your list doesn't contain Longs, it contains Watchs. This is also why the compiler sees it as dubious; contains accepts an Object but it will return false if what you're looking for doesn't have a comparable equals for what's in your list.
You have to iterate over the entirety of your collection to find it in this scenario, especially since you're looking for a specific property on those objects as opposed to a specific, easy-to-provide value.
please how can I fix that. I want to use the contain() to find a
particular object with the matching serial number.
In that case override Watch's equals() to use serialNumber field for comparison.
Then add constructor that accepts serialNumber.
public class Watch {
private final long serialNumber;
public Watch(long serialNumber) {
this.serialNumber = serialNumber;
}
#Override
public boolean equals(Object obj) {
return obj == this ||
(obj instanceof Watch && ((Watch)obj).serialNumber == serialNumber);
}
#Override
public int hashCode() {
return (int)serialNumber;
}
}
Replace if(watchStore.contains(s)){ with if(watchStore.contains(watchToFind)){ where Watch watchToFind = new Watch(s);
you can use contains method from org.apache.commons.lang.ArrayUtils package.
Checks if the value is in the given array.
The method returns false if a null array is passed in.
Parameters:
array the array to search through
valueToFind the value to find
Returns:
true if the array contains the object
long [] imageHashes= {12l,13l,14l,15l};
System.out.println(ArrayUtils.contains(imageHashes, 13l));
I want my custom functions to modify / toggle a boolean variable. Let's say that I have code like
if (OK2continue) { findANDclick(new String[]{"id", "menuButton"});}
if (OK2continue) { findANDclick(new String[]{"src", ".*homeicon_calendar.*"}); }
if (OK2continue) { findANDclick(new String[]{"src", ".*cycle_templates.*"});
I want to make sure that the flow of execution stops once any of the findANDclick functions toggles the variable OK2continue
I managed my functions to modify a String variable using StringBuilder.
Can I do the same for boolean type of variable?
I can't say it is equivalent. But using MutableBoolean offers you a mutable boolean wrapper, similar to the concept of StringBuilder a mutable sequence of characters. See this JavaDoc for details.
Push this code into its own method, and use a return:
if (findANDclick(new String[]{"id", "menuButton"})) return;
if (findANDclick(new String[]{"src", ".*homeicon_calendar.*"})) return;
if (findANDclick(new String[]{"src", ".*cycle_templates.*"})) return;
Given that all your method calls are the same, you could also use a loop:
String[][] buttons = {
{"id", "menuButton"},
{"src", ".*homeicon_calendar.*"},
{"src", ".*cycle_templates.*"},
};
for (String[] button: buttons) {
if (findANDclick(button)) return;
}
You might or might not find that more readable.
You need to clarify your reference to your usage of StringBuilder.
Assuming:
You pass reference of the StringBuilder to your method. String is changed in method. If this the case, then see #Gordon Murray Dent's answer.
Your boolean flag is visible in the method but is not passed. A simple Boolean will do.
package sof_6232851;
public class SideEffectingMethod {
static Boolean flag = false;
public static void main(String[] args) {
flag = true;
System.out.format ("flag is %b\n", flag);
clickMe();
System.out.format ("flag is %b\n", flag);
}
/** this method side-effects instance variable flag */
public static void clickMe () {
flag = !flag;
}
}
[edit list item #2 to reply to OP comment]:
Note that #2 is not really recommended. You mention your desire for "readable" code. Side-effecting methods works against that goal.
public class ReturnValuesForFunAndProfit {
public static void main(String[] args) {
presentUI();
}
public static void presentUI() {
if(!clickMe("woof")) return;
if(!clickMe("meow")) return;
if(!clickMe("hello")) return;
}
public static boolean clickMe (String blah) {
// your logic here; this ex. always returns true
return true;
}
}
Well, the concept of StringBuilder is to create a mutable and extendable String wrapper (meaning the string can be extended via append and the like :) ). You'd still have to pass it as a parameter to the method in order to modify it (or use a static var - not recommended).
Since boolean can't be extended, the only similarity would be the parameter to be mutable. So you can use MutableBoolean as Gordon suggested, but you'd still have to pass it.
Another option would be to return a boolean from findANDclick(...) and use the boolean opperators like: findAndClick(...) || findAndClick(...) || findAndClick(...) which would only execute the next findAndClick(...) if the previous returned false.
Since that option is somewhat hard to maintain, especially since you might have side effects in findAndClick(...) as well as being quite static and hard to read if you have more calls in there, you might want to use a list of function objects:
class FindAndClickExecutor {
public FindAndClickExecutor(String[] params) {...}
public boolean findAndClick() {...}
}
List<FindAndClickExecutor> faces = ...; //initialize appropriately
for( FindAndClickExecutor face : faces ) {
boolean ok2continue = face.findAndClick();
if( !ok2continue ) {
break;
}
}
Edit: since there seem to be other methods as well, you might use a more general list:
interface Executor {
boolean execute();
}
class FindAndClickExecutor implements Executor {
public boolean execute() {} // findAndClick code here, set parameters using constructor
}
class FindAndSelectOptionExecutor implements Executor {
public boolean execute() {} // findAndSelectOption code here
}
List<Executor> testCase1Sequence = ...; //initialize test case 1
List<Executor> testCase2Sequence = ...; //initialize test case 2
for( Executor ex : testCase1Sequence ) {
boolean ok2continue = ex.execute();
if( !ok2continue) {
break;
}
}
This example could also be expanded on, e.g. by using a more complex return value containing the continue flag and maybe more data (use interface here as well).
Edit 2: you could also use some scripting to define and the builder pattern to generate the list of executors for each test case.