3

I want to return a value from the loop. My code is as follows:

public long findLocationId(String location) throws SystemException
    {

        long locId = 1;

        List<Location> locationList = LocationLocalServiceUtil.getLocations(-1,-1);

            for(Location findLoc : locationList)  {
                if(location == findLoc.getLocationName())  {
                    locId = findLoc.getLocationId();

                    **return locId;**
                }
            }

    }

When I try to put the return value in loop I get an error saying to include a return statement.

How should I change my code so that I can return a value from the loop itself?

I want to return the new locId value which I get in the loop and not the value which I set initially as locId = 1; I want to return the new value of locId which i get from the loop

Seeya K
  • 1,221
  • 6
  • 27
  • 43

14 Answers14

4

There are various approach to this problem.

  1. Use while loop
  2. Use for loop with additional stop condition
  3. Use break key word.

Let first create a template before introduce our logic:

public long findLocationId(String locationName) throws SystemException
    {

        if(locationName == null) { //Here we cover first issue. 
            throw new IllegalArgumentException("THe locationName must not be null");
        }

        long locId = Long.MIN_VALUE; //We declare a default value that will be returned if none match found. 

        Collection<Location> locationList = getLocationList(); //The location can be read from another method so we are not binded to field.

        if(locationList == null || locationList.isEmpty()) {
            return locId; // Or throw an exception about invalid state.
        }


        //Place for the logic


        return locId;

    }

Typically when we do not know when we want to stop the iteration, it is a sign that we should start with while loop.

So lets try it.

Solution 1 - The while way.

 Iterator<Location> iterator = locationList.iterator();

        while(iterator.hasNext() && Long.MIN_VALUE != locId) {

            Location location = iterator.next();

            if(locationName.equalsIgnoreCase(location.getLocationName())) {
                locId = location.getLocationId(); // This will change the locId, so second condition will be no longer true and loop will end.
            }

        }

The pros: - It works

The cons: - Leave the iterator

We should not leave iterators, as this is error prone. This lead us to next solution.

Solution 2 - We use the pattern for iterator instead of while.

 for(Iterator<Location> iterator2 = locationList.iterator();iterator.hasNext() && Long.MIN_VALUE != locId;) {

            Location location = iterator.next();

            if(locationName.equalsIgnoreCase(location.getLocationName())) {
                locId = location.getLocationId(); // This will change the locId, so second condition will be no longer true and loop will end.
            }
        }

Pros - It works

Cons - It complicated, we must thing about the stop, when reading this code.

As above solution is not easy to read is should be also removed.

Solution 3 - Why break is useful.

for(Location location : locationList) {

            if(locationName.equalsIgnoreCase(location.getLocationName())) {
                locId = location.getLocationId();
                break;
            }

        }

Pros - It works - It readable

Cons - None

Conclusion is that the code should be readable. Using break, we point that we found the match and we do not want to progress anymore.

Fine. But what about the case when location was found ?

OP example we return 1L. This is not the best choice as is very likely that this value could be used as ID.

In previous examples i have used the min value of long. This is acceptable for some cases but, still we need to validate the method result, and also document it.

The final solution present additional loop exit, that is return key word.

public long findLocationId(String locationName) throws SystemException
    {

        if(locationName == null) { //Here we cover fist issue. 
            throw new IllegalArgumentException("THe locationName must not be null");
        }

        Collection<Location> locationList = getLocationList(); //The location can be read from another method so we are not binded to field.

        if(locationList == null) {
            throw new IllegalStateException("THe location list was not initialized"); 
        }

        for(Location location : locationList) {

            if(locationName.equalsIgnoreCase(location.getLocationName())) {
                return location.getLocationId(); //We exit from the method.
            }

        }

        throw new SystemException("Could not found location for name:" + locationName); 

    }

Additional note

In the example OP have location == findLoc.getLocationName(), the problem with this code is that we should not use == to compare objects types (details). As we deal with String class recommended method is to use method String#equals(Object) or 'String#equalsIgnoreCase(String)'. For this example i have used the second option.

Community
  • 1
  • 1
  • Thanks Vash for such a nice explanation. But I accepted the first among all correct answers since there are many duplicate answers :) – Seeya K Apr 05 '13 at 08:53
  • Vash: Well I have accepted your answer. Nice explanation like I said before.. and many different ways of doing the same – Seeya K Apr 05 '13 at 09:31
  • Thanks Vash for the EDIT. You really made everything very clear. Thanks again!! :) – Seeya K Apr 05 '13 at 10:04
  • No problem. Come back to stack any time. And share your experience to ;-). – Damian Leszczyński - Vash Apr 05 '13 at 10:07
  • I am always here on this site posting my difficulties. Btw, I liked your coding skills. Do you have any blog where I can followe your coding skills? The one you mentioned in your profile here is in Polish and I cannot understand.. – Seeya K Apr 05 '13 at 10:09
  • The link in my profile is an OS web that my friend run. Sometimes I contribute there some articles but in Polish. As by my blog, I am still not ready with it to release it for public. But i can advise you the [John Skeet] (http://msmvps.com/blogs/jon_skeet/) blog. You will find there many interesting article, John is also SO user. – Damian Leszczyński - Vash Apr 05 '13 at 10:34
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/27641/discussion-between-cya-k-and-vash) – Seeya K Apr 05 '13 at 13:46
3

It is because all control flows in a function should end in returning a long value.

In your case assume that there is no match in the list, so the return statement will never get executed that is why the error is reported.

To fix this you can add a return statement at the end of the function with a default value, or if your logic permits you can throw an execption saying location is not found.

Solution 1: If you want to return 1 if there is no match

public long findLocationId(String location) throws SystemException {
    long locId = 1;
    List<Location> locationList = LocationLocalServiceUtil.getLocations(-1,
            -1);
    for (Location findLoc : locationList) {
        if (location == findLoc.getLocationName()) {
            locId = findLoc.getLocationId();
            break;
        }
    }
    return locId;
}

Solution 2: Throw an exception if the location is not found

public long findLocationId(String location) throws SystemException {
    List<Location> locationList = LocationLocalServiceUtil.getLocations(-1,
            -1);
    for (Location findLoc : locationList) {
        if (location == findLoc.getLocationName()) {
            return findLoc.getLocationId();
        }
    }
    throw new SystemException("Unable to find the location");
}
Arun P Johny
  • 384,651
  • 66
  • 527
  • 531
3

It is because there isn't always going to be a case when location == findLoc.getLocationName(). Even if that IS the case, the java compiler doesn't know what sort of input you are giving your program so it it telling you that there could be a case when the function doesn't return anything even though it MUST return a long.

Just return -1L or something that your pogram can consider to be "not found" at the end of the function.

Sanchit
  • 2,240
  • 4
  • 23
  • 34
1

There must a default return statement. As there are only return statement which also is conditional, compiler will force you for default one.

public long findLocationId(String location) throws SystemException{

    long locId = 1;
    List<Location> locationList = LocationLocalServiceUtil.getLocations(-1,-1);
    for(Location findLoc : locationList)  {
         if(location == findLoc.getLocationName())  {
             locId = findLoc.getLocationId();
                return locId;
         }
    }
    return locId; // default return value
}
Subhrajyoti Majumder
  • 40,646
  • 13
  • 77
  • 103
1
public long findLocationId(String location) throws SystemException
    {

        long locId = 1;

        List<Location> locationList = LocationLocalServiceUtil.getLocations(-1,-1);

            for(Location findLoc : locationList)  {
                if(location == findLoc.getLocationName())  {
                    locId = findLoc.getLocationId();


                }
            }
          return locId;
    }

try this you get anwser

suresh manda
  • 659
  • 1
  • 8
  • 25
0
public long findLocationId(String location) throws SystemException
    {

        long locId = 1;

        List<Location> locationList = LocationLocalServiceUtil.getLocations(-1,-1);

            for(Location findLoc : locationList)  {
                if(location == findLoc.getLocationName())  {
                    locId = findLoc.getLocationId();
                    break;
                }
            }
            return locId;
    }
akluth
  • 8,393
  • 5
  • 38
  • 42
0

That is because your return statement in your if statement, which is conditional. Hence, if there is a case where the control never enters the if block, the method would be left without a return value.

Therefore, have a default return at the end of the method.

Rahul
  • 44,383
  • 11
  • 84
  • 103
0

In case your if statement didn't find any location that is equal to your location means what will happen. That is why this compilation error happens. So you must add a return statement at end of your method.

public long findLocationId(String location) throws SystemException
{

    long locId = 1;

    List<Location> locationList = LocationLocalServiceUtil.getLocations(-1,-1);

        for(Location findLoc : locationList)  {
            if(location == findLoc.getLocationName())  {
                locId = findLoc.getLocationId();

                **return locId;**
            }
        }
return
}
Gunaseelan
  • 14,415
  • 11
  • 80
  • 128
0

You should use break statement to come out from the loop if you do not use to execute the loop more.

You can not use the return statement inside a for loop as this return statement will call multiple times.

And the method demand only one return statement at a single time.
Here break statement will will just break out of the innermost loop (here for loop).

public long findLocationId(String location) throws SystemException
    {

        long locId = 1;

        List<Location> locationList = LocationLocalServiceUtil.getLocations(-1,-1);

            for(Location findLoc : locationList)  {
                if(location == findLoc.getLocationName())  {
                    locId = findLoc.getLocationId();
                   break;
                }
            }
     return locId;
    }

For more details:
Please visit here

Community
  • 1
  • 1
Shreyos Adikari
  • 12,348
  • 19
  • 73
  • 82
  • This is not entirely correct. `return` will never be called more than once. Calling `return` will end the method `findLocationId` at that point in code. http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html – gordonk Apr 05 '13 at 14:19
0

Your return statement is in an "if" statement, which means it will not be reached if the "if" evaluates to false. You need a return statement outside of the "if" statement.

PowerApp101
  • 1,798
  • 1
  • 18
  • 25
0

The problem is: what would your method return if the condition in your loop is not met?

You need to return a default value, and the return statement needs to be placed after the for-loop.

Jean Logeart
  • 52,687
  • 11
  • 83
  • 118
0

there are 2 issues in your code.

  1. there must be exactly one return for a method, but being in for loop, since its also a conditional flow (it may not even run a single time) you must provide an alternate return statement. though it will return whatever comes first.
  2. there must be a return in every flow. but since your return is in if condition, there would be missing a return statement if if-expression is false. You would then require to provide an alternative return statement outside if. (else compiler will show error)

in your code: for(Location findLoc : locationList) { if(location == findLoc.getLocationName()) { locId = findLoc.getLocationId(); return locId; } } return locId; // adding this would fix the problem

Ankit
  • 6,554
  • 6
  • 49
  • 71
0

You just have to add a return statement in the case the element is not found. Trivial self-contained example:

public class Main {

    public static long findStringIDX(String[] myList, String myString) {

        long locId = 0;

        for (String s : myList) {
            if (myString.equalsIgnoreCase(s)) {
                return locId;
            }
            locId++;
        }
        return -1; // Not found

    }

    public static void main(String[] args) {
        String[] myList = new String[] { "hello", "world", "bobby" };
        System.out.println(findStringIDX(myList, "bobby"));
    }

}
lc2817
  • 3,722
  • 16
  • 40
0

Simple way to do that.

public long findLocationId(String location) throws SystemException
{
  long locId = 1; // but i suggest to put -1
  List<Location> locationList = LocationLocalServiceUtil.getLocations(-1,-1);
  for(Location findLoc : locationList)  {
    if(location == findLoc.getLocationName())  {
      return findLoc.getLocationId();
    }
  }
  return locId;
}
e1che
  • 1,241
  • 1
  • 17
  • 34