mengdiwang / guava-libraries

Automatically exported from code.google.com/p/guava-libraries
Apache License 2.0
0 stars 0 forks source link

Add new find with Function interface to Iterables and Iterators #444

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Iterables.find can return the same data type as the input Iterables. It would 
be nice if it takes a Function in addition to Prediates and allows the Function 
to decide what data type to return. The signature and a sample implementation 
is as follows:

  /**
     * In Iterables
     */
    public static <I, O> O find(Iterable<I> iterable,
                                Function<? super I, O> function){
        return find(iterable.iterator(), function);//support to be Iterators.find(...)
    }

    /**
     * In Iterator
     */
    public static <I, O> O find(Iterator<I> iterator, Function<? super I, O> function){
        while (iterator.hasNext()){
            I input = iterator.next();
            O output = function.apply(input);
            if (output != null) return output;
        }
        return null;
    }

    public static void main(String[] args){
        List<String> numbers = Arrays.asList(new String[]{"one", "two", "three"});

        Integer i = find(numbers, new Function<String, Integer>(){

            @Override public Integer apply(@Nullable String s){
                if ("two".equals(s)) return 2;
                else return null;
            }
        });
        System.out.println(i);//return 2;
    }

Original issue reported on code.google.com by mingfai...@gmail.com on 7 Oct 2010 at 10:53

GoogleCodeExporter commented 9 years ago
p.s. there should be one more interface with default return value.

Original comment by mingfai...@gmail.com on 7 Oct 2010 at 10:54

GoogleCodeExporter commented 9 years ago
just realize i actually need to find multiple values.

Lists.transform is similar but doesn't meet my requirement exactly. I expect 
Lists.transform will process every item, and allow null. And it has to be a 
List (instead of Iterator/Iterable that is more generic)

It would be nice to have a Iterators.findAll( iterator, Function ) method. It 
is similar to Iterators.filter but as it returns a different data type, it 
shouldn't be called a filter. findAll returns non-null elements only.

Original comment by mingfai...@gmail.com on 7 Oct 2010 at 11:16

GoogleCodeExporter commented 9 years ago
Don't you just want Iterables/Iterators.transform? Both already exist.

Original comment by cgdec...@gmail.com on 7 Oct 2010 at 1:45

GoogleCodeExporter commented 9 years ago
Also, if you want non-null elements only, just filter for non-null elements and 
then transform.

Original comment by cgdec...@gmail.com on 7 Oct 2010 at 1:49

GoogleCodeExporter commented 9 years ago
thx. i used Iterables.transform then filter at the end. (i realized Iterables 
also have a transform only after posted the #2 comment)

anyway, the original issue was about returning the first matched object. A 
workaround could be using a transform function that turn the non-matched object 
to null, and then apply a filter. It is still not ideal for at least two cases:
1. if there are really a lot of objects in the iteration or the checking logic 
is actually expensive
2. some iterables may not really designed for scanning to the end. Take a real 
example, in Neo4j, a graph db, it's node traversing return an iterable, that 
the nodes are accessed only when we call the hasNext()/next(). 

anyway, it's just a suggestion. No worry to close the issue if you don't think 
it makes sense. tyvm

Original comment by mingfai...@gmail.com on 7 Oct 2010 at 2:45

GoogleCodeExporter commented 9 years ago
(Note: I'm not a member of this project, just commenting.)

One very important thing that I think you're missing is that filter and 
transform are both lazy. Neither actually iterates through the elements at all.

Iterable<F> iter = ...
Function<F,T> function = ...
T value = get(filter(transform(iter, function), Predicates.notNull()), 0);

When you do the above (using Iterables for get, filter, transform), no 
iteration is going to take place until the get call, and get will stop and 
return a value as soon as the first non-null result is found. There is no 
problem even with an infinite iterable, unless there are no elements matching 
the filter in which case it would just keep iterating forever looking for a 
match.

Original comment by cgdec...@gmail.com on 7 Oct 2010 at 3:16

GoogleCodeExporter commented 9 years ago
I agree with Colin; I think this is best addressed using the existing APIs.

Original comment by kevinb@google.com on 5 Nov 2010 at 6:35

GoogleCodeExporter commented 9 years ago
This issue has been migrated to GitHub.

It can be found at https://github.com/google/guava/issues/<id>

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:15

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 3 Nov 2014 at 9:09