开发者

How to translate this duck-typing (Python) to Java generics?

Consider the following simple Python function by way of example:

def qua开发者_开发百科ntize(data, nlevels, quantizer=lambda x, d: int(floor(x/d))):
    llim = min(data)
    delta = (max(data) - llim)/(nlevels - 1) # last level x == max(data) only
    y = type(data)
    if delta == 0:
        return y([0] * len(data))
    else:
        return y([quantizer(x - llim, delta) for x in data])

And here it is in action:

>>> from random import random
>>> data = [10*random() for _ in range(10)]
>>> data
[6.6181668777075018, 9.0511321773967737, 1.8967672216187881, 7.3396890304913951,
4.0566699095012835, 2.3589022034131069, 0.76888247730320769, 8.994874996737197,
7.1717500363578246, 2.887112256757157]
>>> quantize(data, nlevels=5)
[2, 4, 0, 3, 1, 0, 0, 3, 3, 1]
>>> quantize(tuple(data), nlevels=5)
(2, 4, 0, 3, 1, 0, 0, 3, 3, 1)
>>> from math import floor
>>> quantize(data, nlevels=5, quantizer=lambda x, d: (floor(x/d) + 0.5))
[2.5, 4.5, 0.5, 3.5, 1.5, 0.5, 0.5, 3.5, 3.5, 1.5]

This function certainly has flaws --for one thing, it does not validate arguments, and it should be smarter about how it sets the type of the returned value--, but it has the virtue that it will work whether the elements in data are integers or floats or some other numeric type. Also, by default it returns a list of ints, though, by passing a suitable function as the optional quantizer argument, this type can be changed to something else. Furthermore, if the data parameter is a list, the returned value will be a list; if data is a tuple, the returned value will be a tuple. (This last feature is certainly the weakest one, but it is also the one that I'm least interested in replicating in Java, so I did not bother to make it more robust.)

I would like to write an efficient Java-equivalent of this function, which means figuring out how to get around Java's typing. Since I learned Java (aeons ago), generics were introduced into the language. I've tried learning about Java generics, but find them pretty incomprehensible. I don't know is this is due to early-onset senility, or because of the sheer growth in Java's complexity since I last programmed in it (ca. 2001), but every page I find on this topic is more confusing than the previous one. I'd really appreciate it if someone could show me how to do this in Java.

Thanks!


One solution to the input/output type question might be to use the Number class and its subclasses along with wildcards. If you wanted to accept any type of numerical argument, you could either specify the input type to be Number OR ? extends Number. If the input is a list, the latter form has an advantage as it will ensure that each element of the list is of the same type (which must be a subclass of Number). The ? is known as a Wildcard, and when it is expressed as ? extends Number it is a "Bounded Wildcard", and may only refer to a subtype of the bounding type.

Example:

public List<Number> func(List<? extends Number> data, Number nlevels)

This would take a List of a specific subclass of Number, a Number for the nlevels parameter, and return a List of Numbers

As for the function input parameter, it would be possible to input a Method, though the type checking at this point gets difficult, as you will be passing data of a bounded unknown parameter to a Method object. I am not exactly sure how that would work.

As for the return type, it would be possible to specify another parameter, a class object (likely a ? extends Number again) that the list elements would be cast (or converted) to.

public List<? extends Number> quantize(List<? extends Number> data, 
                                       Number nlevels, 
                                       Method quantizer, 
                                       Class<? extends Number> returnType)

That is an attempt at a possible declaration for your function in Java. The implementation, however, is somewhat more complex.


It's not quite what you asked, but may I suggest trying out Jython? You'd be able to take your Python code and compile directly to Java bytecode. As you haven't used Java since 2001 and you seem to be using Python these days, you may find Jython much easier to work with than having to bring yourself up to speed on all the changes in Java beforehand.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜