3

例として、次の単純な Python 関数を考えてみましょう。

def quantize(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])

そして、ここでそれが実行されています:

>>> 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]

この関数には確かに欠陥があります -- 一つには、引数を検証しません。また、戻り値の型を設定する方法についてはよりスマートにする必要があります -- しかし、データ内の要素が整数または浮動小数点数またはその他の数値型。また、デフォルトでは int のリストを返しますが、オプションの quantizer 引数として適切な関数を渡すことで、この型を別のものに変更できます。さらに、データ パラメータがリストの場合、返される値はリストになります。data がタプルの場合、戻り値はタプルになります。(この最後の機能は確かに最も弱い機能ですが、Java で複製することに最も関心がない機能でもあるため、わざわざそれをより堅牢にすることはしませんでした。)

この関数に相当する効率的なJavaを書きたいと思います。つまり、Java の型付けを回避する方法を考え出すことです。私が Java を学んで以来 (かなり前)、言語にジェネリックが導入されました。Javaジェネリックについて学習しようとしましたが、かなり理解できないことがわかりました。これが早期発症の老化によるものなのか、それとも Java で最後にプログラミングして以来 (約 2001 年) に Java の複雑さが大幅に増加したためなのかはわかりませんが、このトピックに関するすべてのページは、以前のページよりも混乱しています。 1。誰かがJavaでこれを行う方法を教えてくれたら本当にありがたいです。

ありがとう!

4

2 に答える 2

4

入力/出力タイプの問題に対する 1 つの解決策は、Numberクラスとそのサブクラスをワイルドカードと共に使用することです。任意のタイプの数値引数を受け入れたい場合は、入力タイプをNumberORに指定できます? extends Number。入力がリストの場合、リストの各要素が同じ型 (Number のサブクラスである必要があります) であることを保証するため、後者の形式には利点があります。はWildcard?として知られており、表現されると「Bounded Wildcard」であり、境界型のサブタイプのみを参照できます。? extends Number

例:

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

これは、 の特定のサブクラスの List を取り、nlevelsパラメータに を指定して、 の List を返します。NumberNumberNumber

関数の入力パラメータについては、 を入力することもできますがMethod、この時点では境界のある未知のパラメータのデータをMethodオブジェクトに渡すことになるため、型チェックが難しくなります。それがどのように機能するかは正確にはわかりません。

? extends Number戻り値の型に関しては、別のパラメーター、リスト要素がキャスト (または変換) されるクラス オブジェクト (おそらく再び) を指定することが可能です。

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

これは、Java で関数を宣言する試みです。ただし、実装はやや複雑です。

于 2011-08-02T16:43:12.887 に答える
1

ご質問の内容とは少し異なりますが、 Jythonを試してみることをお勧めしますか? Python コードを直接 Java バイトコードにコンパイルできます。2001 年以来 Java を使用しておらず、最近は Python を使用しているように見えるので、事前に Java のすべての変更について理解する必要があるよりも、Jython を使用する方がはるかに簡単であることに気付くかもしれません。

于 2011-08-02T16:25:26.643 に答える