gpt4 book ai didi

Java 泛型 : How to create a to-n collection with configurable value holder type

转载 作者:搜寻专家 更新时间:2023-11-01 02:38:20 25 4
gpt4 key购买 nike

我的目标是创建一个基于 Java 集合的 1 对 n 容器类。 (大致类似于 Map<String,Collection<Double>>——对于单个字符串,映射可以包含 n 个 double 值。例如,对于键“坐标”,容器可以包含值 [3.1、4.3、7.2])。

一个必需的特性是可以自由定义每个键包含 n 个元素的类型。因此,上面示例中的 Collection 应该可以替换为 List 或 Set。

以下必须是可能的,如果是,目标就达到了:

OneToN2<String, Double, List<Double>> cl = 
new OneToN2<>( ArrayList.class );
OneToN2<String, Double, Set<Double>> cs =
new OneToN2<>( HashSet.class );

现在我从以下代码开始:

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." );
}
}
}

请注意,我只保留了最少的一组操作来展示我的意图。

到目前为止一切顺利:我能够在技术上表达我的意图并且编译器接受了它,所以第一步成功了。

现在问题来了:我无法创建上述类型的实例 :)

以下示例用例显示了预期用途,但它们都不起作用:

预期的解决方案是:

// 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 );

真可惜,但我知道编译器无法推断出 ArrayList.class 是一个列表。所以我尝试了不太理想但可以接受的替代方案:

// 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 容器是固定的。为了防止这种情况,我正在寻找一个通用实现。)

最佳答案

如果您使用的是 Java 8,Supplier 将为您清理一切。

public class OneToN2<K,V, CT extends Collection<V> > extends HashMap<K, Collection<V>>
{
private final Supplier<CT> _containerCtor;

/**
* Create an instance.
*/
public OneToN2( Supplier<CT> _containerCtor )
{
this._containerCtor = _containerCtor;
}

...

    /**
* Create a new instance of the to-n container.
*/
private Collection<V> makeToN()
{
return _containerCtor.get();
}
}

然后你可以像这样实例化你的集合:

public static void main(String[] args) {
OneToN2<String, Double, List<Double>> x = new OneToN2<>(ArrayList::new);
}

关于Java 泛型 : How to create a to-n collection with configurable value holder type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40780757/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com