1

I'd like to have a for each loop to loop through an array of objects.. but only the objects that are an instance of a specific class. To be more clear of what I mean, I've included the example below...

//Declare a list of employee objects
List<Employee> employees = new ArrayList<Employees>;

//Create some employees...
Employee employee = new Employee();
//The class EmployeeExtender extends and is a child of Employee 
EmployeeExtender employeeExtended = new EmployeeExtender(); 

//Now add all the employees, even the ones of different instances to the list
employees.add(employee);
employees.add(employeeExtended);

Now I would like to introduce a for each loop that loops through the employees list that only loops through employees that are an instance of EmployeeExtender. I could just loop through each one and use an if statement (as shown below) but I would like to know if there was a way without making a seperate list to do this.

//I would like to only loop through employees that are an instance of EmployeeExtender
for(Employee employee : employees){
    //I would like to not have this if statement...
    if(employee instanceof EmployeeExtender){
        //do logic...
    }
}

Are my only options creating separate lists, or using the if statement? I'd like to know if there are more options. Thanks.

15
  • 3
    One way or another if they're all in the same list then you need to iterate over each object in the list. You could filter using any of a number of mechanisms to make it seem like you're only hitting the ones you want, e.g., zeroturnaround.com/rebellabs/…, but you have a single list, and without interrogating each item, how would you know what it is? Commented Feb 22, 2018 at 20:39
  • 1
    You could do something like employees.stream().filter(e -> e instanceOf ExmployeeExtender).forEach( . . . ) ; well, unless you use a custom list which provides a iterator only on the objects that are instances of EmployeeExtender, but that's really just moving your filtering around. Commented Feb 22, 2018 at 20:40
  • 1
    @DawoodibnKareem, why is it the worst of the three options? Commented Feb 22, 2018 at 20:41
  • 1
    In simple words, if you put apples, oranges and fruits in the basket of fruits, and you want to do something only with apples, you'll have to pick one by one item from your basket and see if is it an apple or not... IMHO, either you should reconsider your data structure (e.g implementing map), or use the streams (better option than yours), or use your own code. Commented Feb 22, 2018 at 20:50
  • 1
    I don't know if this is compatible with your logic, but you could write a function in Employee which does nothing and overwrite it in EmplyoyeeExtender with the function doing the logic. And in the loop call always this function. Commented Feb 22, 2018 at 20:53

2 Answers 2

3

One option that hasn't been considered is to dispatch the logic to an empty method, that's overridden in the subclass you're interested in. I don't think I'd recommend doing it this way, but you did ask for options other than the straightforward for-each / instanceof way of doing it.

public class Employee {
    public void doTheLogic(TheClassYoureCallingFrom caller) {
    }
}

public class EmployeeExtended extends Employee {
    @Override
    public void doTheLogic(TheClassYoureCallingFrom caller) {
        // The actual logic goes here.
    }
}

public class TheClassYoureCallingFrom {

    List<Employee> employees = new ArrayList<Employees>;

    public void theMethodYoureCallingFrom() {
        for (Employee employee : employees) {
            employee.doTheLogic(this);
        }
    }
}

Of course, if you're not using any of the methods of the calling class, there's no need to pass it as a parameter.

Sign up to request clarification or add additional context in comments.

Comments

1

You could use Streams:

employees.stream()
    .filter(employee -> employee instanceof EmployeeExtender)
    .forEach(employee -> {
        //do logic
    });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.