10

I would like to flatten arbitrary deeply nested collections/structures of elements of some type T in Java, optimally with

  • only having a live view and not a copied collection;
  • not only handling Collections, but also Iterator, arrays of T of arbitrary dimension, Iterable, and all these structures arbitrarily mixed and nested;
  • statical type-safety.

Is there a java library which can handle this?


Guava seems to only handle one nesting level, i.e. Collection<Collection<T>> --flatten--> Collection<T>.

lambdaj looks promising: can I somehow combine on(), asIterator() and flattenIterator() to achieve this? In a statically type-safe manner?

DaveFar
  • 6,260
  • 3
  • 39
  • 80
  • 3
    Not based on either of the above, but perhaps a `DeepIterator` class that is constructed with a `Collection` whose `next()` method looks at the next `Object` and if it is a `instanceof Collection` then pushes the current `iterator` on `Stack` and recurses into that `Collection`'s iterator. – Miserable Variable Sep 15 '11 at 13:02
  • Yes, I've implemented some iterators that way. Having to make a case distinction for arrays of arbitrary dimensions and Iterators is pretty fiddly, though. And there is no static type-safety :( Since lambdaj probably implements it at least as good, I don't think I should do that implementation... – DaveFar Sep 15 '11 at 13:13
  • 2
    What do you mean static type safety here? Since the Collection (ADG actually) can contain elements of different types, the Iterator can only provide `Object`s. Am I missing something? – Miserable Variable Sep 15 '11 at 13:23
  • At least for all arbitrarily deeply nested Collections you can detect at compile time that the leafs are all of type T. Since lambdaj offers a lot of functions that feel dynamically typed (e.g. invoking a method on each item), but are actually still statically typed, I hope lambdaj can handle even more structures and checks at compile time. – DaveFar Sep 15 '11 at 13:37
  • `DeepIterator` aproach sounds promising, but I don't think you can achieve general and statical type-safety solution. I don't see how you can even express such entity in Java. – Jarek Przygódzki Sep 15 '11 at 13:39
  • Collection, and each element is either a single element or a lambdaj proxy object implementing Interface1. – DaveFar Sep 15 '11 at 13:44
  • Or make a disjoint union data type with functional java's fj.data.Either. So on the whole, it's definitely not easy, but static typing can often do more then you'd expect at first glance (even without flow dependent types or type inference). – DaveFar Sep 15 '11 at 13:46
  • Regarding `Collection – Miserable Variable Sep 15 '11 at 14:21
  • As I've said, I am interested in static type-safety, so the compiler would give me an error (lambdaj's proxy object implementing Interface1 is supposed to be statically type-safe). – DaveFar Sep 15 '11 at 14:24

3 Answers3

2

Guava will probably support this eventually :

http://code.google.com/p/guava-libraries/issues/detail?id=174

(It might be easiest to read that from the bottom up, since the thinking on it has shifted a few times over its lifetime.)

Kevin Bourrillion
  • 38,833
  • 12
  • 69
  • 84
1

Not based on either of the above, but perhaps a DeepIterator class that is constructed with a Collection whose next() method looks at the next Object and if it is a instanceof Collection then pushes the current iterator on Stack and recurses into that Collection's iterator.

Miserable Variable
  • 27,314
  • 13
  • 69
  • 124
0

I think this may help: Arrays.deepToString(myCollection.toArray())

Suraj Chandran
  • 23,444
  • 11
  • 58
  • 92
  • For retrieving Strings, yes. For retrieving elements of type T, this unfortunately does not help. – DaveFar Sep 15 '11 at 13:39
  • @daveball i think it would still work, you wanna check code for deepToString and also depends on whether type T has implemented toString – Suraj Chandran Sep 15 '11 at 13:46
  • 2
    `deepToString()` does not handle Arrays either. That is, if one of the elements is an `Array` the it will call `toString` on it, not `Arrays.deepToString`. Strange but true. – Miserable Variable Sep 15 '11 at 13:59
  • 1
    @DaveBall I think Suraj means `getDeclaredMethods()` which will tell you if the `Class` implements `toString()` itself. But I don't know how that helps. You are not interested in knowing what the string representation of the object is, you want an Iterator over all the objects – Miserable Variable Sep 15 '11 at 14:02