1

I have here the following piece of code, it is designed to find and return a product object, using a string input to compare with names of all products.

public Product find(String input){

    for(int i = 0; i <Products.size();i++)
    {
         if(input ==Products.get(i).getName()){

         return Products.get(i);
        }   
    }   
}

I am having two problems with it.

A) The return value is inside the IF statement, so the main method find() does not have a return value. therefore I am receiving an error message about this.

B) If the user types in the name of a product that does not exist, then no product will be found, in which it shouldn't return anything, but I am not sure how to do this. The result is currently being used to remove products, so if it passes a null product object to be removed this would probably cause an error output in the remove method.

I am new to programming so my apologies if this is a novice question, any help would be very much appreciated.

  • 5
    You should use `equals()` method to compare String values: `if(input.equals(Products.get(i).getName()))` – Hülya Jan 15 '20 at 17:51

3 Answers3

5

(A) and (B) are really just the same problem. :-)

You need to have code after the loop that does one of two things when no match is found:

  1. Throws an exception, or

  2. Returns null

...or return an Optional as Andreas shows you in his answer.

Returning null is standard if not finding a match is common and normal. Throwing an exception is standard if not finding a match is unusual and unexpected.


A couple of other notes on that code:

  1. Don't use == to compare strings, use equals; details

  2. I assume Products is either an instance variable (field) or a static variable. If so, it shouldn't be initially-capped. Standard Java naming conventions have instance and static variables start with a lower case letter.

  3. If Products is an instance variable, I strongly recommend using this. to access it (this.Products, not just Products), although it's a matter of style; Java does allow you to leave it off.

  4. If Products is an array or a List (given the size() method, it looks like a list), you'd probably be better off using the enhanced for loop.

  5. Excessive use of blank lines is discouraged. Again, just a matter of style. :-)

  6. It's best to be consistent with your placement of curly braces ({}) (at the end of the line, or on its own on the next line, but not both in the same code). :-)

Taking all of the above into account, assuming Products is an instance variable:

public Product find(String input) {
    for (Product product : this.products) {
        if (input.equals(product.getName())) {
            return product;
        }   
    }   
    return null;
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 1
    Very solid answer! – RobOhRob Jan 15 '20 at 18:00
  • Thank you very much indeed for your help with this, I appreciate the extra effort in helping to improve the overall code! Is it correct to think that once the return statement is read - whether inside the for loop or not - the overall find method ends? Also I have never seen this code (Product product : this.products), understand it loops through all array elements however could point me towards a source explaining which parts of the code does what ? – Gherkin in God mode Jan 15 '20 at 18:21
  • 1
    @InitialisingAttributes Correct, when a `return` statement is executed, no other code in the method will be executed *(except `finally` blocks)*. --- `for (Product product : this.products)` is known as an *enhanced* `for` loop. See *any Java guide* on `for` loops for more detail, e.g. [The Java™ Tutorials](https://docs.oracle.com/javase/tutorial/java/nutsandbolts/for.html) or [GeeksforGeeks](https://www.geeksforgeeks.org/loops-in-java/) or [w3schools](https://www.w3schools.com/java/java_for_loop.asp) or ... – Andreas Jan 15 '20 at 18:40
1

The recommended way to return nothing, as of Java 8, is to return an Optional:

public Optional<Product> find(String input) {
    for (Product product : products) {
        if (product.getName().equals(input)) {
            return Optional.of(product);
        }
    }
    return Optional.empty();
}

This forces the caller to check if something was returned.

For more information, see e.g. Guide To Java 8 Optional.


For pre-Java 8, or just to do it old-style, return a null value:

public Product find(String input) {
    for (Product product : products) {
        if (product.getName().equals(input)) {
            return product;
        }
    }
    return null;
}

It is still up to the caller to check if something was returned, i.e. to check whether null is returned. It is however too easy for the caller to forget to do that, which is why use of Optional is preferred.

Andreas
  • 154,647
  • 11
  • 152
  • 247
-1

I would suggest using the Optional class for achieving your goals. Your code can easily be replaced by this code. Assuming that you have a list of products, the following code can be used :

public Optional<Product> find(String name) {
    List<Product> products = productDao.fetchAll();
    return products.stream().filter(p -> StringUtils.equals(p.name, name)).findFirst().orElseThrow(<Insert some excpeption builder>);
}
  • Why `StringUtils.equals(...)`? What library is that even from? Why not the built-in [`Objects.equals(...)`](https://docs.oracle.com/javase/8/docs/api/java/util/Objects.html#equals-java.lang.Object-java.lang.Object-)? – Andreas Jan 15 '20 at 18:32
  • 1
    What's the point of using `Optional` if you're never going to return an empty optional, but throw an exception instead? – Andreas Jan 15 '20 at 18:34