私の目標は、Javaコレクションに基づいて1対nのコンテナクラスを作成することです。 (ほぼMap<String,Collection<Double>>
のようなものです - 単一の文字列の場合、マップはn個の倍精度を保持できます。たとえば、キー "coordinate"の場合、コンテナは値[3.1,4.3、7.2]を保持できます)。Javaジェネリックス:設定可能なバリューホルダータイプを使用してto-nコレクションを作成する方法
必要な特徴は、キーごとにn個の要素を保持する型を自由に定義できることです。したがって、上記の例のCollectionは、ListまたはSetで置き換えられる必要があります。
次のことが可能でなければならず、それがある場合には、目標に到達する:
package com.fun.with.generics;
import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.HashMap;
/**
* A map that maps a single key to n values.
*
* @param <K> The key type.
* @param <V> The value type.
* @param <V> The type used as container for the to-n elements.
*/
@SuppressWarnings("serial")
public class OneToN2<K,V,CT extends Collection<V> > extends HashMap<K, Collection<V>>
{
private final Constructor<CT> _containerCtor;
/**
* Create an instance.
*/
public OneToN2(Class<CT> claß)
{
try
{
_containerCtor = claß.getConstructor();
}
catch (Exception e)
{
throw new IllegalArgumentException("Need default ctor.");
}
}
/**
* Add a single key value pair.
*
* @param key The key.
* @param element The element to add.
*/
synchronized public void add(K key, V element)
{
Collection<V> ct = get(key);
if (ct == null)
{
ct = makeToN();
put(key, ct);
}
ct.add(element);
}
/**
* Add an element for multiple keys.
*
* @param keys The keys to add.
* @param element The element the keys refer to.
*/
synchronized public void add(Collection<K> keys, V element)
{
for (K c : keys)
add(c, element);
}
/**
* Get a newly allocated container holding the n values.
*/
@Override
public Collection<V> get(Object key)
{
Collection<V> n =
super.get(key);
Collection<V> result =
makeToN();
result.addAll(n);
return result;
}
/**
* Create a new instance of the to-n container.
*/
private Collection<V> makeToN()
{
try
{
return _containerCtor.newInstance();
}
catch (Exception e)
{
throw new InternalError("Could not create to-n collection.");
}
}
}
注私は唯一の最小セットを保持:
OneToN2<String, Double, List<Double>> cl =
new OneToN2<>(ArrayList.class);
OneToN2<String, Double, Set<Double>> cs =
new OneToN2<>(HashSet.class);
は今、私は次のコードで開始私の意図を示す手術の
これまでのところ、私は技術的に自分の意図を表現することができ、コンパイラはそれを受け入れたので、最初のステップで成功しました。
は今問題に:私は上記の型のインスタンスを作成することはできませんよ:)
次の例のユースケースは、使用目的を示すが、それらのいずれも取り組んでいる。
意図したソリューション
// Declaration (this compiles):
OneToN2<String, Double, List<Double>> x;
// Initialisation (does not compile). Error is Type mismatch: cannot
// convert from OneToN2<String,Double,ArrayList>
// to OneToN2<String,Double,List<Double>>
x = new One2N2<>(ArrayList.class);
Bummerですが、コンパイラはArrayList.classがListであると推測できないことを理解しています。
// Declaration (this compiles):
OneToN2<String, Double, ArrayList<Double>> x;
// Initialisation (does not compile). Error is Type mismatch: cannot
// convert from OneToN2<String,Double,ArrayList>
// to OneToN2<String,Double,ArrayList<Double>>
x = new One2N2<>(ArrayList.class);
が再び多かれ少なかれ一定のエラーメッセージが表示されて、残念:だから私はあまり理想的ではなく許容可能な代替手段を試してみました。
問題はどこですか?
(なぜ私はそれを望んでいるのですか?学問的興味、ジェネリックスの楽しさですが、正直なところ、いくつかのシステムで同様のタイプを作成したため、to-nコンテナが固定されているのでコードが重複しています。
あなたはグアバmultimapのを使用して考えられていますか? –