Java Forum / General / July 2005
My idea for filtering an Enumeration or Iterator
Robert Maas, see http://tinyurl.com/uh3t - 13 May 2005 13:00 GMT I'm thinking of programming a wrapper for an Enumeration or Iterator, FilteredEnumeration or FilteredIterator respectively, which filters the objects passing through it. Each would be a sub-class of the corresponding API class. Each wrapper class would of course override the two or three methods of the corresponding API class, simply calling the API method repeatedly until the filter criterion is satisfied or there's nothing next. These could be chained to filter on more than one condition.
For example, you could filter according to membership in some class per the following constructor:
FilteredEnumeration(Enumeration en, Class cl, int inheritMode, int filterMode)
cl can be a class or an interface
inheritMode = EXACT_MATCH | ANY_SUBCLASS filterMode = ASSERT_MATCH | DISCARD_NON_MATCH | DISCARD_MATCH (mode ASSERT_MATCH throws an exception if object doesn't match)
For another example, you could filter on an arbitrary predicate that takes one parameter of type Object, the predicate of course being a Method:
FilteredEnumeration(Enumeration en, Method predicate) static boolean predicate(Object | someClass)
predicate can be any static method of signature boolean <method>(Object) If en is a FilteredEnumeration using ASSERT_MATCH or DISCARD_NON_MATCH and with cl = someClass1, then predicate can be any method whose signature is static boolean <method>(someClass2) where someClass2 is the same class or any super-class of someClass1.
Does anybody know of such a filter already implmented and freely available, or can I safely program it without having to worry I'm re-inventing the wheel?
Also, I have a technical question. I'm thinking of compiling a library of static methods which use (*) only well-known classes. If the source code is available, then a whole bunch of such selected static methods could be appended into one big java source file and compiled with no problems to create a custom utility-library class suitable for small machines where you can't afford to have the entire class that each static method came from, or if each method costs money and you don't need them all so don't want to pay for them all. But what if the source isn't available? Is it possible to find a static method within a class object, clone it, and put the clone into a custom-library class being built, without any problems? I'm thinking that a static method is basically unrelated to the class it's in, so it can be copied from there and pasted anywhere else without problem, but did I overlook something?
* (To "use" a class means to accept parameter which is instance of that class, or use local variable or temporary value which is instance of that class, or call static method of that class, or return object which is instance of that class.)
So I'm thinking of a net-accessible database which indexes zillions of different static Java methods and allows people to download any specific method they need for their particular application.
This contrasts with instance methods and constructors, where if you want to make any use of objects which are instances of somebody's custom class, you probably want to download the entire class as a unit rather than try to break it apart. So for that usage the database would list each complete class as a single unit rather than having separate entries for each method. (Of course it would still *document* each public method individually so you could see if the class had what you wanted before downloading.)
Has anybody already set up a per-single-static-method library like that, or can I safely go ahead and implement it without "re-inventing the wheel"?
Back to my first idea above: I'm thinking that each constructor for different kind of filtered enumeration/iterator is really constructing a different kind of object, so each such constructor, and the two or three corresponding methods (hasNext, next, delete), should be in a separate class, all of which are sub-classes of the interface FilteredEnumeration or FilteredIterator. But an interface can't be a sub-class of a regular class, right? So maybe I have to turn this around backwards and instead of using a constructor I need to have a set of static methods which are factories for constructing objects which really are each instances of sub-classes of Enumeration or Iterator, but all the user needs know is that the source code can declare the variable (holding the return value from the factory) to be of type Enumeration or Iterator and inheritance works correctly to pick the appropriate override of hasNext/next/delete in each case. The user of my API never need know that the actual objects are of classes named ClassFilteredEnumeration or PredicateFilteredEnumeration etc. So anyway, these factories for making custom objects of sub-classes of Enumeration or Iterator, would *not* satisfy the criterion for membership in the per-method database, because their return value is not of a well-known type, so the user would need to download the entire class consisting of one factory and two or three methods to be used on the return value of the factory. But at least by using static factory methods instead of constructors, the names can all be the same even though each is in a different class. (There really is a differently-named constructor for each class, but those are private constructors, so the users never need be aware they're included in the downloads.)
Oh, one last: The factor would be called MakeFilteredEnumeration or MakeFilteredIterator, of course.
Ross Bamford - 13 May 2005 13:49 GMT > I'm thinking of programming a wrapper for an Enumeration or Iterator, > FilteredEnumeration or FilteredIterator respectively, which filters the [quoted text clipped - 4 lines] > there's nothing next. These could be chained to filter on more than one > condition. At first glance your idea would work, but I'm not sure it's really in the spirit of Collections. Iterator and Enumeration are more lightweight objects, such that instead of saying 'Filter all *** from this iterator' you would instead ask the collection 'Give me an iterator over all ***' or whatever.
The java.util.Collections class provides a number of similar classes.
> Also, I have a technical question. I'm thinking of compiling a library > of static methods which use (*) only well-known classes. If the source [quoted text clipped - 15 lines] > that class, or call static method of that class, or return object > which is instance of that class.) public static Connection getSharedConnection(); { return sharedConn; }
You would need to consider how things like this would be handled. Also, what about methods that access the 'class' expecting a certain type of class (perhaps newInstance'ing it)? I'm not sure it would be a workable solution, and in any case breaking classes up to make big 'function library' classes (.h) goes against the fundemental principals of OOP in Java I believe.
> So I'm thinking of a net-accessible database which indexes zillions of > different static Java methods and allows people to download any > specific method they need for their particular application. ?
> Back to my first idea above: I'm thinking that each constructor for > different kind of filtered enumeration/iterator is really constructing [quoted text clipped - 23 lines] > constructors, so the users never need be aware they're included in the > downloads.) Yes, I think I see, you mean you would use a factory to return an Iterator implemented by your new class. See java.util.Collections for some examples of similar ideas with collections.
Cheers, Ross
 Signature [Ross A. Bamford] [ross AT the.website.domain] Roscopeco Open Tech ++ Open Source + Java + Apache + CMF http://www.roscopec0.f9.co.uk/ + info@the.website.domain
Roland - 13 May 2005 13:56 GMT > I'm thinking of programming a wrapper for an Enumeration or Iterator, > FilteredEnumeration or FilteredIterator respectively, which filters the [quoted text clipped - 33 lines] > available, or can I safely program it without having to worry I'm > re-inventing the wheel? [snip long explanation] (sorry, I didn't read it)
There's Apache's Commons Collection library which provides a filter iterator: <http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_1/org/apache /commons/collections/iterators/FilterIterator.html> <http://jakarta.apache.org/commons/collections/>
An Enumeration can be adapted quite easily to an Iterator (Commons Collection already provides such an adapter: EnumerationIterator).
 Signature Regards,
Roland de Ruiter ___ ___ /__/ w_/ /__/ / \ /_/ / \
Dale King - 18 May 2005 05:38 GMT >> I'm thinking of programming a wrapper for an Enumeration or Iterator, >> FilteredEnumeration or FilteredIterator respectively, which filters the [quoted text clipped - 41 lines] > > <http://jakarta.apache.org/commons/collections/> And another similar one that I just discovered is JGA. See this article where it talks about this sort of thing:
http://jga.sourceforge.net/docs/AddingAlgorithms.shtml
 Signature Dale King
Robert Maas, see http://tinyurl.com/uh3t - 21 Jun 2005 07:35 GMT > From: Roland <roland@phony.biz> > There's Apache's Commons Collection library which provides a filter > iterator: > <http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_1/org/apache /commons/collections/iterators/FilterIterator.html> > Decorates an iterator such that only elements matching a predicate > filter are returned. Unfortunately the result isn't itself an iterator, so any code calling it as if it were an iterator would break: boolean hasNext() Returns true if the underlying iterator contains an object that matches the predicate. java.lang.Object next() Returns the next object that matches the predicate. So hasNext returns true even if there aren't any more items that match the predicate, and then next throws an exception because the underlying iterator runs off the end. I'm referring to the following standard code: while (it.hasNext()) { Object obj = it.next(); /* do something with obj */ } The exception will occur whenever the very last item in the underlying iteration fails the predicate, so after all the predicate-satisfying items have been fetched, all of which are before that last item, hasNext returns true because that last item hasn't yet been processed.
With a bug like that, the call to hasNext is virtually useless, so the code basically needs to be rewritten like this: while (true) { Object obj; try { obj = it.next(); /* do something with obj */ } catch (Exception ex) { break; }
The right way to implement a filter iterator is to do lookahead to make sure there really is another item in the underlying iteration that satisfies the predicate. But then the remove method wouldn't work after the lookahead is done. But in the standard loop the lookahead is done only after finishing processing the old item, which might get deleted, just before starting to look for the next item, so if the code is used that way the lookahed for hasNext wouldn't be a problem. But still it wouldn't be a true iterator. In summary, there is no way to write an iterator wrapper completely correctly, but one way is not as bad as the other, and the way jakarta did it is the worst of the two.
With an enumeration, there's no delete method, so lookahed is no problem regardless of whether standard outer loop is done or something less standard is done.
IMO it's stupid to use an iterator unless you really do plan to be deleting elements as you go along. It's overkill for a task where an enumeration would have sufficed, and given that it precludes making a filter that works correctly it's a bad idea.
Now a filter-deleter-iterator could be made to work, or a deleter-iterator. In addition to, or instead of, a predicate for returns, you pass a predicate for deletion. Two modes could be: - Return *everything* that passes the return-predicate, even if it was deleted because it passed the delete-predicate. - Return only items that weren't deleted.
Actually there are a whole lot of different modes possible with two predicates, and not worth detailing here.
By the way, a reasonable alternate would be a default-value iterator or enumeration, whereby the call to the next method contains a default value that is returned if it runs off the end of the sequence. So then you'd never need either a hasNext call (with lookahed and associated problems if you're deleting anything) nor a try...catch block.
> <http://jakarta.apache.org/commons/collections/> * BidiMap interface for maps that can be looked up from value to key as well and key to value
"as well and" should read "as well as" to be correct English.
* Composite collections that make multiple collections look like one
If the same element occurs in more than one Map or Set which are combined, how are the duplicates eliminated? Which of the copies stays and which are like gone? If a new item is added, which of the pieces does it go to? Has this been worked out precisely?
* Identity map that compares objects based on their identity (==) instead of the equals method
Isn't that already trivial by supplying a comparator like that?
The WebSite says that the collections framework was added with version 1.2 of J2SE (I presume) but it doesn't say whether 1.2 is all you need to run this new add-on or whether a more recent version is actually needed. Do you know anyone who can say what's needed? Also, is this new add-on free or costs money?
> An Enumeration can be adapted quite easily to an Iterator (Commons Not efficiently, because an Enumeration doesn't provide in-place delete as you go along, so the only way to be guaranteed to implement delete if all you have to start with is an Enumeration is to have kept a list of everything you already enumerated and at the first delete request to go back and delete from the very toplevel of the collection then start a new Enumeration from the front again and if the sequence is now grossly different from the old sequence, such as if rehashing occurred, then you have to do a super hack checking every item to see whether it's in the list you already did before the delete in which case you skip it after the delete. In short, it's not worth bothering to even try such messy and necessarily inefficient programming.
Note that it is *not* sufficient to make a list of items requested for delete and then actually delete them only when the simulated Iterator is finished, because the required behaviour is that the item is *immediately* deleted from the original collection whenever requested.
> Commons Collection already provides such an adapter: > EnumerationIterator Let me look at it ... ah, I already looked at that and commented on it. The so-called "Adapter to make Enumeration instances appear to be Iterator instances" does *not* satisfy the semantics of an iterator, so that introductory/title description is a lie.
I think that team has shoddy programmers who can't figure out flaws in their logic that are obvious to me. They need to hire me to weed out all the stuff they did that's broken and either scrap it for good if it's impossible to do it efficient and correct or do it *right* if possible. I'm available and have much need for earned income. If I had my choice, I'd rather do something new and useful, such as create a flexible interval-arithmetic package, but if there's any money for work on fixing this broken project I'd be glad to do that.
public void setEnumeration(Enumeration enumeration) Sets the underlying enumeration. Parameters: enumeration - the new underlying enumeration
No restriction on *when* you can pull that trick? So if halfway through a simulated iteration based on an enumeration which is likewise halfway through, if you switch the underlying enumeration to something totally unrelated, an enumeration of a completely different collection for example, what are the semantics? Has anybody on this team thought this out? Or is that not allowed, you can only specify the underlying enumeration before you call next() the first time, but nobody thought of specifying that in the JavaDoc?
But thanks for pointing me this WebSite so I know what I did and a lot more has already been done, so I won't waste my time without pay doing any more of that sort of thing. The Jakarta project there will either turn out good (if somebody sees my notes and takes a re-look at what they did to fix the problems, or if they happen to get somebody else equally bright to give them a kick in the butt), or crap (if they continue their current ways, and produce something that introduces as many new bugs as 1.1 had regarding thread-deadlocks etc. that had to be removed in later versions, those "deprecated" methods from 1.1). In any case it'd be a waste of time to duplicate what they've attempted.
Now if I'm mistaken, if there's nothing wrong where I pointed out problems, please let me know! I'm always ready to learn if I misunderstood something.
angrybaldguy@gmail.com - 24 Jun 2005 19:41 GMT > With an enumeration, there's no delete method, so lookahed (sic) is no > problem regardless of whether standard outer loop is done or something [quoted text clipped - 4 lines] > enumeration would have sufficed, and given that it precludes making a > filter that works correctly it's a bad idea. A lovely assertion, but mostly irrelevant, for two reasons:
1. Enumerations aren't available on the most common collection interfaces in java.util (List, Set, and Map), and read-only iteration is likely the most common use of Iterators over these collections (it certainly is in my own code). The documentation specifically states that Iterator takes the place of Enumeration.
Hell, the new for-loop syntax in 1.5 is a read-only way of using an Iterator.
2. remove() is documented as being an optional operation for iterators, so failing to support remove() doesn't violate the contract for Iterator. While I don't like the idea of "optional" members of interfaces (preferring subinterfaces), there is precedent for it in the Java APIs.
Robert Maas, see http://tinyurl.com/uh3t - 28 Jul 2005 06:15 GMT > From: angrybaldguy@gmail.com > Enumerations aren't available on the most common collection > interfaces in java.util (List, Set, and Map). That seems to be a rather moot point, considering that: (1) Given any specific implementation of such an interface, it's rather trivial to sub-class it to implement an enumeration for that class. So then you declare your objects to be of that sub-class instead of the API class. (2) If you absolutely need a generic class that includes more than one such sub-classed implementation class, with objects declared to be ambiguously of the generic class instead of specifically of one of the various implementation classes, and you absolutely need Enumeration to be defined over that whole generic class instead of just over each specific implementation, so that you can compile Enumeration code that doesn't care which implementation class happens at runtime, you can make a runtime interface as I demonstrated a few weeks ago.
Also, I prefer "weak enumerations" instead anyway. Single method getNext or whatever which returns a default EOF value when it's reached the end, otherwise returns the next item in the sequence, avoiding the need to first test isNext and then somehow trust it when in fact it sometimes lies and getNext then throws exception due to the bug.
> While I don't like the idea of "optional" members of interfaces > (preferring subinterfaces), there is precedent for it in the Java APIs. There's precedent for a whole lot of bad ideas. They should all be deprecated rather than glorified as examples to emulate elsewhere.
Chris Uppal - 13 May 2005 14:01 GMT > I'm thinking of programming a wrapper for an Enumeration or Iterator, > FilteredEnumeration or FilteredIterator respectively, which filters the > objects passing through it. You might want to consider making wrappers for Iterables too. If you have a FilteredIterable<E> which wraps an instance of java.lang.Iterable<E> (and which itself implements the same interface) then you'll be able to use the new for-loops on your wrapped object.
> Is it possible to find a static method within a class > object, clone it, and put the clone into a custom-library class being > built, without any problems? It's possible, but messier than you'd like. If the static method doesn't refer to other static methods or static fields of the class then it's at least logically possible. But if it does refer to other static members then you'd have to copy the static methods too, and do something similar for static fields (but then you'd have to find and copy the initialisation code too, unless they fields were initialised to constants). Another problem is that the bytecode format makes heavy use of the so-called "constants pool", and that pool is shared between all the methods of a class. So you'd have to copy/merge the relevant constants into your target class, /and/ find and fix-up all the bytecodes that refer to it (which isn't necessarily easy since there are issues to do with the wide versions of bytecodes).
All in all, it's certainly possible, and might even be quite interesting to do (if you like that sort of thing), but it's hard to imagine it being worth the effort. Especially since I suspect many organisations that supply bytecode without source, will have proscriptions against copying, modifying, or reverse-engineering their code.
-- chris
Robert Maas, see http://tinyurl.com/uh3t - 30 Jun 2005 06:27 GMT > From: "Chris Uppal" <chris.uppal@metagnostic.REMOVE-THIS.org> > You might want to consider making wrappers for Iterables too. That's not an option at this time. I don't have access to any system capable of running whatever version of Java has them. I have only 1.3.1 on my laptop, and the modem is not working so I have no way to download anything newer. So I'm limited to practicing what's available on my laptop, and with the modem broken I can't even upload the results of my work to show anyone. The version available on my shell account on the ISP is 1.2.2, so I'm limited to that for anything I can show anyone online, and my access is text only so I can't show any awt/swing stuff, only stdio and CGI.
It would take a source of seed money to provide a newer development environment, and I don't know any source of such for my Java stuff.
> Is it possible to find a static method within a class > object, clone it, and put the clone into a custom-library class being > built, without any problems?
> It's possible, but messier than you'd like. If the static method > doesn't refer to other static methods or static fields of the class > then it's at least logically possible. Yeah, what I had in mind was like the methods in the Math class which have only two constants E and PI. I'd have to track the dependencies, like if some trig function was implemented by multiping the argument by I and then taking the hyperbolic function or somesuch, so I'd be sure to include anything needed by what was asked-for. So the customer of a high-level optional function would pay for the required low-level utilities plus the one high-level function.
> But if it does refer to other > static members then you'd have to copy the static methods too, and do [quoted text clipped - 3 lines] > use of the so-called "constants pool", and that pool is shared between > all the methods of a class. Hmm, slight mess, sigh.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|