user3221155
user3221155

Reputation: 53

Java Filtering in collections

I have a list of objects as below,

Emp e1  = new Emp(10,"Anitha",1000,"AE");
Emp e2  = new Emp(20,"Chaitanya",2000,"SE");
Emp e3  = new Emp(30,"Chaitanya",3000,"SE");
Emp e4  = new Emp(40,"Deepthi",2100,"AE");
Emp e5  = new Emp(50,"Deepthi",2200,"CE");
Emp e6  = new Emp(60,"Deepthi",2300,"BE");
Emp e7  = new Emp(70,"Anitha",2300,"BE");
Emp e8  = new Emp(80,"Anitha",2400,"ME");
Emp e9  = new Emp(90,"Sita",2200,"CE");
Emp e10 = new Emp(100,"Hari",2200,"CE");
Emp e11 = new Emp(110,"Krishna",2200,"CE");

I would like to filter the values on unique name and also filter on same name like

1.on unique name : output should be

(50,"Deepthi",2200,"CE")
(100,"Hari",2200,"CE")
(110,"Krishna",2200,"CE")

and sharing the same name :

like output

(10,"Anitha",1000,"AE")
(70,"Anitha",2300,"BE")
(80,"Anitha",2400,"ME")
(20,"Chaitanya",2000,"SE");
(30,"Chaitanya",3000,"SE");
(40,"Deepthi",2100,"AE");
(50,"Deepthi",2200,"CE");
(60,"Deepthi",2300,"BE");

using collections.... Will some one be able to help me?

Thanks in Advance. Nithya

Upvotes: 1

Views: 149

Answers (3)

Marco13
Marco13

Reputation: 54679

As far as I can see, the answers until now assumed that the task was to search for a particular name, or to find elements with unique names - and I think this was not what was asked for.

In order to filter a list in the way that is described in the original question, one could create a map from the "key" (that is, the 'name' in this case) to a list of elements that share this key. Using this map, one can easily find

  • One element for each key that occurs only once in all elements
  • The list of all elements that have a key that occurs at least twice in all elements

These tasks are rather similar, and further generalizations may be possible, but here is one way of how this may be implemented:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class CriterionFilter
{
    public static void main(String[] args)
    {
        List<Emp> list = new ArrayList<Emp>();
        list.add(new Emp(10,"Anitha",1000,"AE"));
        list.add(new Emp(20,"Chaitanya",2000,"SE"));
        list.add(new Emp(30,"Chaitanya",3000,"SE"));
        list.add(new Emp(40,"Deepthi",2100,"AE"));
        list.add(new Emp(50,"Deepthi",2200,"CE"));
        list.add(new Emp(60,"Deepthi",2300,"BE"));
        list.add(new Emp(70,"Anitha",2300,"BE"));
        list.add(new Emp(80,"Anitha",2400,"ME"));
        list.add(new Emp(90,"Sita",2200,"CE"));
        list.add(new Emp(100,"Hari",2200,"CE"));
        list.add(new Emp(110,"Krishna",2200,"CE"));

        Function<Emp, String> keyFunction = new Function<Emp, String>()
        {
            @Override
            public String apply(Emp s)
            {
                return s.getName();
            }
        };
        List<Emp> fiteredOnUnique = filterOnUnique(list, keyFunction);
        System.out.println("Filtered on unique:");
        print(fiteredOnUnique);

        List<Emp> filteredOnSame = filterOnSame(list, keyFunction);
        System.out.println("Filtered on same:");
        print(filteredOnSame);
    }

    private static void print(Iterable<?> elements)
    {
        for (Object element : elements)
        {
            System.out.println(element);
        }
    }

    /**
     * Create a map that maps the keys that are provided for the given
     * elements to the list of elements that have this key
     *
     * @param elements The input elements
     * @param keyFunction The key function
     * @return The map
     */
    private static <T, K> Map<K, List<T>> map(
        Iterable<? extends T> elements, Function<? super T, K> keyFunction)
    {
        Map<K, List<T>> map = new HashMap<K, List<T>>();
        for (T t : elements)
        {
            K key = keyFunction.apply(t);
            List<T> list = map.get(key);
            if (list == null)
            {
                list = new ArrayList<T>();
                map.put(key, list);
            }
            list.add(t);
        }
        return map;
    }

    /**
     * Uses the given key function to compute the keys associated with the
     * given elements, and returns a list containing the element of
     * the given sequence that have unique keys
     *
     * @param elements The input elements
     * @param keyFunction The key function
     * @return The filtered list
     */
    private static <T, K> List<T> filterOnUnique(
        Iterable<? extends T> elements, Function<? super T, K> keyFunction)
    {
        List<T> result = new ArrayList<T>();
        Map<K, List<T>> map = map(elements, keyFunction);
        for (Entry<K, List<T>> entry : map.entrySet())
        {
            List<T> list = entry.getValue();
            if (list.size() == 1)
            {
                result.add(list.get(0));
            }
        }
        return result;
    }

    /**
     * Uses the given key function to compute the keys associated with the
     * given elements, and returns a list containing all elements of
     * the given sequence that have a key that occurs multiple times.
     *
     * @param elements The input elements
     * @param keyFunction The key function
     * @return The filtered list
     */
    private static <T, K> List<T> filterOnSame(
        Iterable<? extends T> elements, Function<? super T, K> keyFunction)
    {
        List<T> result = new ArrayList<T>();
        Map<K, List<T>> map = map(elements, keyFunction);
        for (Entry<K, List<T>> entry : map.entrySet())
        {
            List<T> list = entry.getValue();
            if (list.size() > 1)
            {
                result.addAll(list);
            }
        }
        return result;
    }



    /**
     * Interface for a generic function
     */
    static interface Function<S, T>
    {
        T apply(S s);
    }

}


class Emp
{
    private int i;
    private String name;
    private int j;
    private String whatever;

    public Emp(int i, String name, int j, String whatever)
    {
        this.i = i;
        this.name = name;
        this.j = j;
        this.whatever = whatever;
    }

    @Override
    public String toString()
    {
        return "Emp [i=" + i + ", name=" + name + ", j=" + j + ", whatever=" + whatever + "]";
    }

    String getName()
    {
        return name;
    }
}

(EDIT: Adjusted the first case, see comment in original question)

Upvotes: 0

Reut Sharabani
Reut Sharabani

Reputation: 31339

If you're using java 8 please skip to the end!

I'd probably create a map to do this, but it seems like you're new to Java so I'll describe the more basic way.

You should first create a list(arraylist) like so:

// create an arraylist (list based on an array)
List<Emp> emps = new ArrayList<Emp>();

Then you can add objects to the list:

emps.add(new Emp(10,"Anitha",1000,"AE"));
emps.add(new Emp(20,"Chaitanya",2000,"SE"));
.
.

Now you can start filtering!

So, suppose you have a getName() method in class Emp, you can write a function such as this:

// this function takes a list and a name, and filters the list by the name
public static List<Emp> filterEmpsByName(List<Emp> emps, String name){
    // a place to store the result
    List<Emp> result = new ArrayList<Emp>();
    // iterate over the list we got
    for (Emp emp: emps){
        // save only the elements we want
        if (emp.getName().equals(name)){
            result.add(emp);
        }
    }
    return result;
}

Now, filtering would be a simple matter of calling that function:

// print to standard output the result of our function on the "main" list `emp` with name "Anitha"
for (Emp emp : filterEmpsByName(emps, "Anitha")){
    System.out.println(emp.toString()); // make sure toString() is overridden in Emp class
}

Now for the second part which is a bit more tricky:

// this function takes a list and a name, and filters the list by the name
public static List<Emp> getDistinctlyNamedEmps(List<Emp> emps, String name) {
    // this time we use a map which is A LOT faster for this kind of operation

    Map<String, Emp> result = new HashMap<String, Emp>();
    // iterate over the list we got
    for (Emp emp : emps) {
        // save only the elements we want
        if (result.get(emp.getName()) == null ) {
            result.put(emp.getName(), emp);
        }
    }

    // convert map to list - not mandatory if you can use the map as is...
    return new ArrayList<Emp>(result.values());
}

Notice that you can also write a comparator that compares objects using the name/any other property, but that's beyond the scope of this comment :-)

Putting the whole thing together:

Main class:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Main {

    public static void main(String[] args) {
        // create an [arraylist][4] (list based on an array)
        List<Emp> emps = new ArrayList<Emp>();

        emps.add(new Emp(10, "Anitha", 1000, "AE"));
        emps.add(new Emp(20, "Chaitanya", 2000, "SE"));

        // print to standard output the result of our function on the "main"
        // list `emp` with name "Anitha"
        System.out.println("filterEmpsByName(emps, \"Anitha\") output:");
        for (Emp emp : filterEmpsByName(emps, "Anitha")) {
            System.out.println(emp.toString()); // make sure toString() is
                                                // overridden in Emp class
        }

        // print to standard output the result of our second function on the "main"
        // list `emp`
        System.out.println("getDistinctlyNamedEmps(emps) output:");
        for (Emp emp : getDistinctlyNamedEmps(emps)) {
            System.out.println(emp.toString()); // make sure toString() is
                                                // overridden in Emp class
        }
    }

    // this function takes a list and a name, and filters the list by the name
    public static List<Emp> filterEmpsByName(List<Emp> emps, String name) {
        // a place to store the result
        List<Emp> result = new ArrayList<Emp>();
        // iterate over the list we got
        for (Emp emp : emps) {
            // save only the elements we want
            if (emp.getName().equals(name)) {
                result.add(emp);
            }
        }
        return result;
    }

    // this function takes a list and a name, and filters the list by the name
    public static List<Emp> getDistinctlyNamedEmps(List<Emp> emps) {
        // this time we use a map which is A LOT faster for this kind of
        // operation

        Map<String, Emp> result = new HashMap<String, Emp>();
        // iterate over the list we got
        for (Emp emp : emps) {
            // save only the elements we want
            if (result.get(emp.getName()) == null) {
                result.put(emp.getName(), emp);
            }
        }

        // convert map to list - not necessary
        return new ArrayList<Emp>(result.values());
    }

}

And partial Emp class:

public class Emp {

    private String name;

    public Emp(int stubi, String name, int j, String stubs) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public String toString() {
        return "[" + this.name + "]";
    }
}

Java 8:

Java 8 has lambda expressions (anonymous functions), which are neat tools used in many other languages for filtering as well as other operations.

You can read more about using them here.

Upvotes: 3

Michael
Michael

Reputation: 968

Thats not a collections, while it is a 'list' in the traditional sense, it is not a java.util.ArrayList.

To do this, you might try:

ArrayList<Emp> employeeList = new ArrayList<Emp>();

employeeList.add(new Emp(10,"Anitha",1000,"AE"));
// repeat

Upvotes: 0

Related Questions