Simple Implementation of .NET Array/List's Generic FindAll Method in Java

AID: 912
  • Status: Published

2510 points

  • By
  • TypeTutorial
  • Posted on2009-06-11 at 17:01:40
After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET".  Being the Java nut that I am, I would not have felt complete, if I didn't also play with this topic in Java; therefore, you can also read on "Range Searching Using Java" which has the origins of some of the code used in this article.

What does the FindAll method have to do with anything?
[The FindAll generic method] retrieves all the elements that match the conditions defined by the specified predicate.


Very concise definition for a nice generic method in .NET I found to be similarly short and sweet.  In my research, the goal was to create a more efficient means of searching for values in an array/list that met specific criteria without having to loop through each value.  What I found was the FindAll method proved to be faster both in performance and actual code implementation.

System.Array.FindAll(arrayOfObjects, _
   New Predicate(Of String)(AddressOf MatchRange) _
)
                                    
1:
2:
3:

Select allOpen in new window



Just one line of code to use as FindAll utilizes a delegate function known as a Predicate that takes one argument and returns a true or false if the argument meets criteria specified within the predicate's implementation.

'Delegate implementation for Predicate needed in System.Array.FindAll
Function MatchRange(ByVal n As String) As Boolean
    Return Ranges.MatchRange(n, RANGE_START, RANGE_END)
End Function
                                    
1:
2:
3:
4:

Select allOpen in new window



For a better look at delegates from a Java perspective, you can read "A Java Programmer Looks at C# Delegates" by Steven M. Lewis and Wilhelm Fitzpatrick.

For my simple implementation, I chose to go with a Predicate interface and anonymous inner classes to simulate the delegate functionality.

1

Create Predicate Interface.


/**
 * Predicate interface used to emulate .NET 
 * <code>System.Predicate(Of T)</code>.
 */
package com.blogspot.crossedlogic.rangesearching;

public interface Predicate<T> {
    
    /**
     * @param obj - object to test against predicate criteria.
     * @return boolean flag indicating a match (true) or no match (false).
     */
    public boolean isMatch(T obj);
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:

Select allOpen in new window



2

Create FindAll Function.


In .NET, you can utilize shared (static) functions from the List/Array class or from an instance of an implementation of List; therefore, a findAll method could be added to a custom List implementation in Java, but the code I went with uses a utility class that I could store other functions relating to predicates.

package com.blogspot.crossedlogic.rangesearching;


import java.util.ArrayList;
import java.util.List;


public class Predicates {

    /**
     * Replicate .NET findAll and <code>Predicate</code>.
     * 
     * @param <T>
     * @param array - an array of objects of type <T>.
     * @param match -
     *            <p>
     *            instance of an implementation of the Predicate
     *            interface.
     *            </p>
     * @return List<T> representing all matches found.
     * @see com.blogspot.crossedlogic.rangesearching.Predicate
     */
    public static <T> List<T> findAll(T[] array,
            Predicate<T> match) {
        List<T> lst = new ArrayList<T>();

        for (T obj : array) {
            if (match.isMatch(obj)) {
                lst.add(obj);
            }
        }

        return lst;
    }

    /**
     * Replicate .NET findAll and <code>Predicate</code>.
     * 
     * @param <T>
     * @param list - collection of objects of type <T>.
     * @param match - instance of an implementation of the
     *            Predicate interface.
     * @return List<T> representing all matches found.
     * @see com.blogspot.crossedlogic.rangesearching.Predicate
     */
    @SuppressWarnings("unchecked")
    public static <T> List<T> findAll(List<T> list,
            Predicate<T> match) {
        return findAll((T[]) list.toArray(), match);
    }
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:

Select allOpen in new window


Originally, I implemented only the findAll with array argument in signature as it allowed for use with both arrays and lists through one function, but given the ability to overload methods I added the second as it makes calls easier when searching lists as you can simply pass the List object without having to convert it to an array first.


3

Enjoy!


package com.expertsexchange.articles;


import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import com.blogspot.crossedlogic.rangesearching.Predicate;
import com.blogspot.crossedlogic.rangesearching.Predicates;


public class PredicateMatchExample {

    /**
     * @param args
     */
    public static void main(String[] args) {
        List<Number> numbers = new ArrayList<Number>();
        List<Number> matches;

        for (int i = new Random(System.currentTimeMillis())
                .nextInt(10); i < 100; i += 7) {
            numbers.add(i);
        }

        displayNumbers(numbers, "All Numbers");

        // find all the perfect squares.
        matches = Predicates.findAll(numbers
                .toArray(new Number[] {}),
                new Predicate<Number>() {

                    @Override
                    public boolean isMatch(Number n) {
                        double sqrt = Math.sqrt(n.doubleValue());
                        return Math.ceil(sqrt) == sqrt;
                    }
                });

        displayNumbers(matches, "Perfect Squares");

        // find all numbers less than 50.
        matches = Predicates.findAll(numbers,
                new Predicate<Number>() {

                    @Override
                    public boolean isMatch(Number n) {
                        // mimic .NET delegate method;
                        // utilize existing method for
                        // implementation.
                        return isLessThan50(n);
                    }
                });

        displayNumbers(matches, "Less Than 50");
    }

    static boolean isLessThan50(Number n) {
        return n.intValue() < 50;
    }

    static void displayNumbers(List<Number> numbers, String title) {
        System.out.printf("%s: %s.", title,
                (numbers.size() > 0) ? Arrays.toString(
                        numbers.toArray()).replaceAll(
                        "^\\[|\\]$", "") : "none");
        System.out.println("");
    }
}
                                    
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:

Select allOpen in new window


As mentioned earlier, the anonymous inner class within Java allows you to utilize methods from your main class similar to the delegate function in .NET.  Looks a little more than one line, but hopefully you agree that this is not a lot of Java code for what you are getting.

Predicates.findAll(numbers, new Predicate<Number>() {
    @Override 
    public boolean isMatch(Number n) { 
        return isLessThan50(n); 
    }
});
                                    
1:
2:
3:
4:
5:
6:

Select allOpen in new window



I found the FindAll method very useful and I am hoping you will as well.  In addition, having a Predicate concept in Java may come in handy for other projects as well.


Thanks for taking the time to read the above.  If you have any questions on how the code works that is not explained well enough in the code comments, please post below and I will be happy to clarify.


Happy coding!

Best regards,


Kevin (aka MWVisa1)
Asked On
2009-06-11 at 17:01:40ID912
Tags

Java

,

FindAll

,

Arrays

,

Lists

,

Predicates

Topic

Java Programming Language

Views
1859

Comments

Author Comment

by: mwvisa1 on 2009-10-11 at 12:38:19ID: 4123

Here is an official white paper from Sun, discussing usage of Reflection API to implement delegation in Java using the J++ methodology :
http://java.sun.com/docs/white/sidebar.html

And this follow-up article goes into strongly typed delegates (it references above, so good to read in order linked here) :
http://weblogs.java.net/blog/alexwinston/archive/2005/04/strongly_types_1.html

Regards,
Kevin

Add your Comment

Please Sign up or Log in to comment on this article.

Join Experts Exchange Today

Gain Access to all our Tech Resources

Get personalized answers

Ask unlimited questions

Access Proven Solutions

Search 3.2 million solutions

Read In-Depth How-To Guides

1000+ articles, demos, & tips

Watch Step by Step Tutorials

Learn direct from top tech pros

And Much More!

Your complete tech resource

See Plans and Pricing

30-day free trial. Register in 60 seconds.

Loading Advertisement...

Top Java Experts

  1. for_yan

    893,063

    Sage

    1,000 points yesterday

    Profile
    Rank: Genius
  2. CEHJ

    258,666

    Guru

    1,050 points yesterday

    Profile
    Rank: Savant
  3. mccarl

    93,106

    Master

    3,000 points yesterday

    Profile
    Rank: Wizard
  4. girionis

    90,218

    Master

    0 points yesterday

    Profile
    Rank: Genius
  5. dpearson

    86,565

    Master

    498 points yesterday

    Profile
    Rank: Guru
  6. chaituu

    62,368

    Master

    0 points yesterday

    Profile
    Rank: Sage
  7. gudii9

    57,252

    Master

    1,000 points yesterday

    Profile
    Rank: Master
  8. sharonseth

    47,283

    501 points yesterday

    Profile
    Rank: Master
  9. ksivananth

    39,726

    0 points yesterday

    Profile
    Rank: Genius
  10. gordon_vt02

    28,625

    0 points yesterday

    Profile
    Rank: Guru
  11. simonet

    27,400

    0 points yesterday

    Profile
    Rank: Wizard
  12. mrcoffee365

    23,455

    0 points yesterday

    Profile
    Rank: Genius
  13. dravidnsr

    20,609

    501 points yesterday

    Profile
    Rank: Sage
  14. objects

    20,284

    0 points yesterday

    Profile
    Rank: Savant
  15. knsp

    18,558

    0 points yesterday

    Profile
  16. gurvinder372

    18,104

    0 points yesterday

    Profile
    Rank: Genius
  17. santhanasamy

    16,800

    0 points yesterday

    Profile
    Rank: Master
  18. mplungjan

    16,568

    0 points yesterday

    Profile
    Rank: Savant
  19. stmani2005

    15,089

    1,000 points yesterday

    Profile
    Rank: Master
  20. ramazanyich

    14,200

    0 points yesterday

    Profile
    Rank: Sage
  21. CPColin

    13,836

    0 points yesterday

    Profile
    Rank: Guru
  22. arioh

    13,298

    0 points yesterday

    Profile
    Rank: Guru
  23. zzynx

    12,280

    0 points yesterday

    Profile
    Rank: Genius
  24. alexey_gusev

    12,000

    0 points yesterday

    Profile
    Rank: Genius
  25. Gertone

    11,752

    0 points yesterday

    Profile
    Rank: Genius

Hall Of Fame