Type-safe flattening of nested collections/structures in Java
Asked Answered
B

3

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?

Beset answered 15/9, 2011 at 12:41 Comment(9)
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.Gassaway
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...Beset
What do you mean static type safety here? Since the Collection (ADG actually) can contain elements of different types, the Iterator can only provide Objects. Am I missing something?Gassaway
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.Beset
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.Contortionist
Collection<T extends Interface1>, and each element is either a single element or a lambdaj proxy object implementing Interface1.Beset
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).Beset
Regarding Collection<T extends Interface1? what would happen if some nested element is not a kind of Interface1? Omit those elements? Throw exception?Gassaway
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).Beset
C
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.)

Computerize answered 16/9, 2011 at 3:57 Comment(0)
G
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.

Gassaway answered 15/9, 2011 at 13:48 Comment(2)
I'm having a deja-vu reading your post ;) But it's a good idea to give it as a real answer - let's see its votes...Beset
@DaveBall If I can be downvoted for a correct answer maybe I can upvoted for an partial answer :)Gassaway
V
0

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

Veronique answered 15/9, 2011 at 13:34 Comment(4)
For retrieving Strings, yes. For retrieving elements of type T, this unfortunately does not help.Beset
@daveball i think it would still work, you wanna check code for deepToString and also depends on whether type T has implemented toStringVeronique
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.Gassaway
@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 objectsGassaway

© 2022 - 2024 — McMap. All rights reserved.