1

Lets assume that I have a class with multiple String fields.

public class Person {
    private String address;
    private String first_name;
    //etc

Now lets say that I have a List of Persons:

List<Person>

I want to write a method that can parse this list for a specific string value, e.g. address=="California".

The problem is that I have multiple fields in this class and it would be a lot of code reuse if I make a method for each field.

I could also do:

public List<Person> filter(List<Person> plist, String fieldToParse, String value){
    //simple loop that removes the Person.fieldToParse == Person.value values
}

But is there a simpler, less ugly way for me to do this?

user1413969
  • 1,261
  • 2
  • 13
  • 25
  • 1
    Can you explain why you think that approach is not-simple/ugly? That will give people here some hint on what kind of suggestions you are expecting. – Bhesh Gurung Apr 16 '14 at 16:13

3 Answers3

4

You could take a look at the lambdaj library (https://code.google.com/p/lambdaj/) if your goal is to filter the Person objects by a property. See this question/answer, as well What is the best way to filter a Java Collection?

Community
  • 1
  • 1
sckellough
  • 86
  • 1
  • 2
  • 6
    Java 8 has [Lambda expressions](http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/Lambda-QuickStart/index.html#section3). – Robert Harvey Apr 16 '14 at 16:17
  • +1 lambdaj. Here's an example of filtering: http://code.google.com/p/lambdaj/wiki/LambdajFeatures#Filtering_on_a_condition – earldouglas Apr 16 '14 at 16:19
2

You can use any LAMBDA library or you can implement it by yourself. See my code:

public static List<Person> filter(List<Person> source, String fieldToParse, String value) {
    // Field getter
    Method fieldGetter = null;
    try {
        fieldGetter = Person.class.getMethod("get" + firstUpperCase(fieldToParse));
    } catch (NoSuchMethodException ex) {
        throw new IllegalArgumentException("Invalid field name: " + fieldToParse);
    }

    // Filter
    List<Person> list = new ArrayList<Person>();
    for (Person person : source) {
        try {
            Object obj = fieldGetter.invoke(person);
            //TODO: process NULL here
            if (obj.equals(value)) {
                list.add(person);
            }
        } catch (Exception e) {
        }

    }
    return list;
}

public static String firstUpperCase(String str) {
    if (str == null) {
        return null;
    }
    if (str.isEmpty() == false) {
        char[] chars = str.toCharArray();
        chars[0] = Character.toUpperCase(chars[0]);
        return new String(chars);
    }
    return str;
}

Sample uses:

filter ( source, "address", "abc");
filter ( source, "first_name", "july");
LHA
  • 9,398
  • 8
  • 46
  • 85
1

When you define a method like you suggested you lose the type safety (and some error detection in compile time).
This what will happen if someone will call this method with a filed string that does not exist?

To achieve this goal you can try to use Guava collections library.
There is a filter method in the Collection2 class that gets a predicate.
See http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Collections2.html.

You can provide a helper method that will create a predicate for a predefined set of fields if such filters will be common.

Itay Karo
  • 17,924
  • 4
  • 40
  • 58