get status of an Arraylist in Java - java

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

Related

Using booleans with set and get methods

To summarize I am making a program for a metro ticket system. and I am using set and get methods for it, when it comes to boolean values (since I need to validate that the person enters enough money for the ticket) how am i supposed to put in the main class( it is defined in brain) using the set method and an if statement.Here is a little fraction of the entire code and the rest is on github(https://github.com/alexxei4/subwayticket). The main is basically the class that will be used for interaction with the user and the brain is where alot of the actions are defined.All help is appreciated, please and thank you.
if (Choice1a == 10){
if(subway1.ticketcounter1(true);){
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
}
if(subway1.ticketcounter1(false);){
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
This is not how you evaluate boolean values, you just place the value in an if statement and it will proceed if true and refuse if false, also there is no need to duplicate the statement when you can just place an else block to handle situations that are not true:
if(subway1.ticketcounter1) {
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
}
else {
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
Also do not include semicolons in if statements, that's incorrect syntax. Read more about how to use use boolean values here: https://codingbat.com/doc/java-if-boolean-logic.html
EDIT:
After reading through your Github code I see that ticketcounter1 indeed is a method, but what it's doing is trying to change the value of ticketcounter1 like it's a referenced object, but boolean are primitive data types and can't be referenced, and even if they could it still wouldn't work because Java is a pass-by-value language. Read here for more information on that.
public void ticketcounter1(boolean ticketcounter1){
if (credit1 > total1){
ticketcounter1 = true;
}
else {
ticketcounter1 = false;
}
}
public void ticketcounter2(boolean ticketcounter2){
if (credit2 > total2){
ticketcounter2 = true;
}
else {
ticketcounter2= false;
}
Like the other answer said you should be returning the value as boolean instead of trying to change it:
public boolean ticketcounter1(){
if (credit1 > total1){
return true;
}
else {
return false;
}
}
public boolean ticketcounter2(){
if (credit2 > total2){
return true;
}
else {
return false;
}
}
But all in all your code demonstrated fundamental flaws in understanding how the language works, I would suggest picking up a good Java for beginners kind of book or do some introductory online tutorials. Here is a good place to start your learning journey: https://docs.oracle.com/javase/tutorial/java/index.html
You code is like this
public void ticketcounter1(boolean ticketcounter1){
if (credit1 > total1){
ticketcounter1 = true;
}
else {
ticketcounter1 = false;
}
}
public void ticketcounter2(boolean ticketcounter2) {
if (credit2 > total2){
ticketcounter2 = true;
}
else {
ticketcounter2= false;
}
}
It should be like this. Instead of using the variable and passing it though parameter. Use getter. Besides that your code won't run since subway1.ticketcounter1(true) is giving nothing. It is only changing variables stored in Brain.java. No information is being sent to main.
public boolean ticketcounter1(){
if (credit1 > total1){
return true;
}
else {
return false;
}
}
public boolean ticketcounter2(){
if (credit2 > total2){
return true;
}
else {
return false;
}
}
You can create functions without parameters. I don't know what were you trying to do?
if (Choice1a == 10){
if(subway1.ticketcounter1()){
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
}
if(subway1.ticketcounter1()){
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
}
subway1.ticketcounter1() will give either true and false. Do not use ; in if statement condition. ; ends the statement. Check this guide to learn about use of semi-colon If you do want to use ; The code should look like this
if (Choice1a == 10){
boolean ticketCounter1 = subway1.ticketcounter1();
if(ticketCounter1){
System.out.println("PRINT SUCCESSFUL, COLLECT YOUR TICKET!");
} else {
System.out.println("INSEFFICIENT FUNDS, PLEASE ADD MORE");
}
}
P.S You don't need two ifs if-else would be better in this case
if(condition) {
// Conditions is true
} else {
// Condition is false
}

Java 10 ifPresentOrElse that return boolean

I am a little confused on "how to do this properly":
// return true: if present and number of lines != 0
boolean isValid(Optional<File> optFile) {
return optFile.ifPresentOrElse(f -> return !isZeroLine(f), return false);
}
private boolean isZeroLine(File f) {
return MyFileUtils.getNbLinesByFile(f) == 0;
}
I know the syntax is not correct and not compiling, but it's just for you to get the idea.
How can I turn this into 'clean code'?
i.e. avoid doing:
if (optFile.isPresent()) {//} else {//}
Dealing with boolean return type(easily inferred Predicates), one way to do that could be to use Optional.filter :
boolean isValid(Optional<File> optFile) {
return optFile.filter(this::isZeroLine).isPresent();
}
But, then using Optionals arguments seems to be a poor practice. As suggested in comments by Carlos as well, another way of implementing it could possibly be:
boolean isValid(File optFile) {
return Optional.ofNullable(optFile).map(this::isZeroLine).orElse(false);
}
On another note, ifPresentOrElse is a construct to be used while performing some actions corresponding to the presence of the Optional value something like :
optFile.ifPresentOrElse(this::doWork, this::doNothing)
where the corresponding actions could be -
private void doWork(File f){
// do some work with the file
}
private void doNothing() {
// do some other actions
}

SQL IN condition in Java

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.

How to break out and return an object from a recursion after meeting a certain condition is met

I have a recusrion function where i want to return the object as soon as certain condition is met . The function looks like this .
GroupNavigationItemSRO getCategorySpecificNavItem(List<GroupNavigationItemSRO> items,String url) {
GroupNavigationItemSRO sro = new GroupNavigationItemSRO();
if(items != null && !items.isEmpty()){
for(GroupNavigationItemSRO item : items) {
if(item.getUrl().equals(url)) {
LOG.info("Found Specific Url");
return item;
}
else
getCategorySpecificNavItem(item.getChildren(),url);
}
}
return null;
}
Now the function returns null and i get why its happening despite meeting the criteria .How to avoid that and end the recursion as soon as the url is found.
What you want to do is stop looking when you've found it, but recurse until you do.
The main problem with your existing code is that the recursive call's return value is ignored. Instead, you want to look at that return value and, if it's not null, return it; you're done:
for(GroupNavigationItemSRO item : items) {
if(item.getUrl().equals(url)) {
LOG.info("Found Specific Url");
return item;
}
else {
GroupNavigationItemSRO itemFromChild = getCategorySpecificNavItem(item.getChildren(),url);
if (itemFromChild != null) {
// Found!
return itemFromChild;
}
}
}

Refactor code with return statements

The "if" blocks with checkcustomers are exactly used in other methods in this class, so there is a lot of code dublication for same checks. But I cant also directly extract this checksomethings to one single method because they have return values.
Some good ideas to refactor this code? I just modified this code to simplify here, so dont get caught on minor issues in this code(if any), Basically question is how to a extract a piece of code to a method(because it is dublicated on other methods) when there are many returns in that current method.
public Details getCustomerDetails(){
if(checkifcustomerhasnoboobs){
..worry about it..
return new Details("no");
}
if(checkifcustomerplaytenniswell){
..do find a tennis teacher
return new Details("no cantplay");
}
//...ok now if customer passed the test, now do the some real stuff
//
//
CustomerDetails details= getCustomerDetailsFromSomewhere();
return details;
}
How about this?
public Result checkSomethings() {
if ( checksomething1 ) {
return ResultCheckSomething1;
}
if ( checksomething2 ) {
return ResultCheckSomething2;
}
return ResultCheckNone;
}
public Details getCustomerDetails(){
Result result = checkSomethings();
switch ( result ) {
case ResultCheckSomething1:
return new Details("message1");
case ResultCheckSomething2:
return new Details("message2");
default:
return getCustomerDetailsFromSomewhere();
}
}
The Result... codes would be in an enum.
Maybe something like this?
public Details getCustomerDetails(){
boolean isError = checksomething1() || checksomething2();
String message = checksomething1() ? "message1" : "message2";
return isError ? new Details(message) : getCustomerDetailsFromSomewhere();
}
If you try to avoid call check functions twice just keep it results
public Details getCustomerDetails(){
boolean check1 = checksomething1();
boolean check2 = checksomething2();
String message = check1 ? "message1" : "message2";
return (check1 || check2) ? new Details(message) : getCustomerDetailsFromSomewhere();
}
Replace the returns with assignments to a result variable that remains null until the first assignment to it. Each block could be replaced by a function that returns null if its condition for changing the result is false.
As pointed out in a comment by herman, this only works if null is not a possible result of one of calls.
public Details getCustomerDetails(){
Details result = null;
if(checksomething1){
..error
result = new Details("message1");
}
if(result == null) {
if(checksomething2){
..error
result = new Details("message2");
}
if(result == null){
result = getCustomerDetailsFromSomewhere();
}
return result;
}
I would do this:
public Details getCustomerDetails(){
Details invalidDetails = checkForInvalidCustomer();
if (invalidDetails !=null) {
return (invalidDetails);
}
//...ok now if customer passed the test, now do the some real stuff
//
//
CustomerDetails details= getCustomerDetailsFromSomewhere();
return details;
}
public Details checkForInvalidCustomer() {
if(checkifcustomerhasnoboobs){
..worry about it..
return new Details("no");
}
if(checkifcustomerplaytenniswell){
..do find a tennis teacher
return new Details("no cantplay");
}
// nulls means valid customer
return (null);
}
Basically, for your specific example, I'm using null so that I can differentiate the case where none of the conditions matched, vs either condition matched. That way I can use a single if statement. Now, if you wanted to return null, you would need to modify this solution slightly, perhaps use some constant for flagging the case instead of using null.
Using Java 8, you can refactor into a method that returns an Optional<...> value.
Statements like return x; would be replaced by return Optional.of(x) (assuming x cannot be null). The default return statement at the end would be return Optional.empty().
Then you can use return optional.orElseGet(() -> ...)) to compute the value for the case where none of the original return statements would be reached.

Categories

Resources