我怎样才能创建< T扩展Map< ? ,? > > Map类型容器的类型拆分操作?

时间:2014-07-30 15:50:42

标签: java generics

我已经实现了一种将HashMap类型容器拆分成相同大小的块的方法。但是,现在这种方法对我的应用程序来说还不够。它限制我的应用程序扩展。因此,我尝试将其泛型类型更改为<T extends Map<?,?>。但是,每当我更改这个新类型时,我都会面临更多难题,例如&#34;如何创建泛型类型数组或实例&#34;。即使我在网上搜索,我也没有摆脱。如何将我的方法更改为新的通用类型?

我的方法;

public static <Type1, Type2> 
HashMap<Type1, Type2>[] 
split(HashMap<Type1, Type2> hashTable, int chunkSize) {     

    int numberOfChunks = ((int) Math.ceil( hashTable.size() / (double)chunkSize))

    HashMap<Type1, Type2> []chunks = new HashMap[numberOfChunks]; 

    Set<Type1> keys = hashTable.keySet();

    int i = 0, j = -1;
    for(Type1 key : keys){
        if((i % chunkSize) == 0 ){
            j = j + 1;
            chunks[j] = new HashMap<Type1, Type2>();
        }
        chunks[j].put(key, (hashTable.get(key)));
        i = i + 1;
    }

    return chunks;
}

我想将此方法更改为

public static <T extends Map<?,?>> 
T[] 
split(T hashTable, int chunkSize) {     

    int numberOfChunks = ((int) Math.ceil( hashTable.size() / (double)chunkSize))

    T []chunks = new T[numberOfChunks];  // Problem I

    Set<Type1> keys = hashTable.keySet();

    int i = 0, j = -1;
    for(Type1 key : keys){
        if((i % chunkSize) == 0 ){
            j = j + 1;
            chunks[j] = new T();  // Problem II
        }
        chunks[j].put(key, (hashTable.get(key)));
        i = i + 1;
    }

    return chunks;
}

我如何转向这种新的通用类型,或者如何修复这些问题的来源,标有// Problem

2 个答案:

答案 0 :(得分:0)

对不起,你为什么不尝试这样的事呢

public static Map[] split(Map hashTable, int chunkSize) {     

    int numberOfChunks = ((int) Math.ceil( hashTable.size() / (double)chunkSize));

    Map[] chunks = new HashMap[numberOfChunks]; 

    Set keys = hashTable.keySet();

    int i = 0, j = -1;
    for(Object key : keys){
        if((i % chunkSize) == 0 ){
            j = j + 1;
            chunks[j] = new HashMap();
        }
        chunks[j].put(key, (hashTable.get(key)));
        i = i + 1;
    }

    return chunks;
}

你只是拆分地图,这里不需要强制执行类型。

答案 1 :(得分:0)

你想要实现的目标并非易事,因为你将遇到需要解决的2个问题。但首先,将该方法签名更改为:

public static <K, V, M extends Map<K, V>> M[] split(M table, int chunkSize)

(Key K,Value V和Map M}这样,你可以拆分你想要的任何地图。

第一个问题是您无法(轻松)创建通用数组,但您可以使用this workaround

另一个问题是你不能简单地创建new HashMap<>()来填充你的数组(如果你的地图不是HashMap怎么办?),那么你可以:

  1. 如果您使用Java 1.8(或1.7版本的旧版本界面),请使用Supplier<? super M>
  2. 访问表格的课程&#39;反射构造函数
  3. 选择1,我已将代码修改为:

    public static <K, V, M extends Map<K, V>> M[] split(M table, int chunkSize,
            Supplier<? extends M> mapCreator) {
    
        int numberOfChunks = (int) Math.ceil(table.size() / (double) chunkSize);
    
        M[] chunks = (M[]) Array.newInstance(table.getClass(), numberOfChunks);
    
        Set<K> keys = table.keySet();
    
        int i = 0, j = -1;
        for (K key : keys) {
            if ((i % chunkSize) == 0) {
                j = j + 1;
                chunks[j] = mapCreator.get();
            }
            chunks[j].put(key, (table.get(key)));
            i = i + 1;
        }
    
        return chunks;
    }
    

    使用测试代码:

    static class MyTreeMap<K, V> extends TreeMap<K, V> {
    }
    
    public static void main(String[] main) {
        HashMap<String, Integer> map1 = new HashMap<>();
        map1.put("one", 1);
        map1.put("two", 2);
        map1.put("three", 3);
        HashMap[] res = split(map1, 2, HashMap::new);
        Arrays.stream(res).forEach(System.out::println);
    
        MyTreeMap<Double, Boolean> map2 = new MyTreeMap<>();
        map2.put(.5, true);
        map2.put(5d, false);
        MyTreeMap[] res2 = split(map2, 1, MyTreeMap::new);
        Arrays.stream(res2).forEach(System.out::println);
    }
    

    输出结果为:

    {one=1, two=2}
    {three=3}
    {0.5=true}
    {5.0=false}
    

    所以它似乎正在发挥作用。