7

The question but in C#. So does Java have C#'s command? I need it for Matches-SearchTerm-Files-relationship.

foreach(var i in BunchOfItems.SelectMany(k => k.Items)) {}

[Why not for-loops?] I have done such structures in nested for loops but they soon become bloated. So I prefer something more succint like the above.

public static Stack<Integer[]> getPrintPoss(String s,File f,Integer maxViewPerF)
{
    Stack<File> possPrint = new Stack<File>();
    Integer[] poss = new Integer[4]();
    int u,size;
    for(File f:files)
    { 
        size = f2S(f).length();
        u = Math.min(maxViewsPerF,size);
        for(int i=0; i<u;i++)
        {
           // Do something --- bloated, and soon out of control
           // wants more succintly

        }
    }
    return possPrint;
}
1
  • 1
    This library has a selectMany() implementation that would look like this for your requirement: for(val i : BunchOfItems.selectMany(bunchItemSelector()) { }. See github.com/nicholas22/jpropel-light Commented Oct 8, 2011 at 10:33

6 Answers 6

10
for (List<Object> lo : list) {
    for (Object o : lo) {
        // etc etc
    }
}

I don't think there's a simpler solution.

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

1 Comment

The OP is asking for a Linq-type of solution that C# provides. He already knows how to iterate through Lists. He wants an elegant solution. Unfortunately, Java does not have something equivalent to Linq.
7

If you can get the data into an Iterable<Iterable<T>>, then you can get from that to a flattened Iterable<T> using Guava's Iterables.concat method. If what you have is really an Iterable<S>, with some way to get from an S to an Iterable<T>, well, then you have to first use Iterables.transform to view that as the Iterable<Iterable<T>> needed by concat.

All this will look a lot nicer if and when Java has something resembling closures, but at least today it's possible.

http://guava-libraries.googlecode.com

Comments

3

With Java 8, you can say

Collection bunchOfItems = ...;
bunchOfItems.stream().flatMap(k::getItems).forEach(i -> /* operate on i */);

or

Item[] bunchOfItems = ...;
Stream.of(bunchOfItems).flatMap(k::getItems).forEach(i -> /* operate on i */);

depending upon whether you have a Collection or an Array.

1 Comment

Can you please explain your code here?
1

Have about half a year patience until JDK7 is final which will include Closures. This provides simliar syntax and the same possibilities as LINQ which was demonstrated in the answer you're talking about.

Comments

1

I have my own version. Waiting desperately for Closures in Java :

public static <T, E> Iterable<T> transformMany(Iterable<E> iterable, Func<E, Iterable<T>> f) {
    if (null == iterable)
        throw new IllegalArgumentException("null iterable");
    if (null == f)
        throw new IllegalArgumentException("null f");

    return new TransformManyIterable<E, T>(iterable, f);
}

public interface Func<E, T> {
    T execute(E e);
}

public class TransformManyIterable<TOriginal, TResult> implements Iterable<TResult> {
    private Iterable<TOriginal> iterable;
    private Func<TOriginal, Iterable<TResult>> func;

    public TransformManyIterable(Iterable<TOriginal> iterable,
            Func<TOriginal, Iterable<TResult>> func) {
        super();
        this.iterable = iterable;
        this.func = func;
    }

    class TransformIterator implements Iterator<TResult> {
        private Iterator<TOriginal> iterator;
        private Iterator<TResult> currentIterator;

        public TransformIterator() {
            iterator = iterable.iterator();
        }

        @Override
        public boolean hasNext() {
            if (currentIterator != null && currentIterator.hasNext())
                return true;
            else {
                while (iterator.hasNext()) {
                    Iterable<TResult> iterable = func.execute(iterator.next());
                    if (iterable == null)
                        continue;
                    currentIterator = iterable.iterator();
                    if (currentIterator.hasNext())
                        return true;
                }
            }

            return false;
        }

        @Override
        public TResult next() {
            if (currentIterator != null && currentIterator.hasNext())
                return currentIterator.next();
            else {
                while (iterator.hasNext()) {
                    Iterable<TResult> iterable = func.execute(iterator.next());
                    if (iterable == null)
                        continue;
                    currentIterator = iterable.iterator();
                    if (currentIterator.hasNext())
                        return currentIterator.next();
                }
            }
            throw new NoSuchElementException();
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    @Override
    public Iterator<TResult> iterator() {
        return new TransformIterator();
    }

}

Usage:

    Iterable<SomeType> result = transformMany(input, new Func<InputType, Iterable<SomeType>>() {
        @Override
        public Iterable<SomeType> execute(InputType e) {
            return new ArrayList<SomeType>();
        }
    });

Comments

1

The SelectMany method is part of LINQ which is .Net-specific. This question asks about a LINQ equilvalent for java. Unfortunately, it doesn't look like there is a direct equivalent.

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.