将两个基本数据类型的数组转换为Map,然后将结果Map转换为这两个数组。

3

我有两个数组,一个是 int 类型的,另一个是 string 类型的。如何将这两个数组转换为 map?

我的代码。首先,我将 int 类型的数组转换为包装类 Integer:

   public static Integer[] toObject(int[] array) {
        Integer[] result = new Integer[array.length];
        for (int i = 0; i < array.length; i++) {
            result[i] = new Integer(array[i]);
        }
        return result;
    }

接着,我将两个数组转换成了映射表

public static <T,V> HashMap<T, V> toHM(T[] array, V[] array2) {
        HashMap<T,V> h = new LinkedHashMap<>();

        for(int i= 0; i < array.length; i++){
            h.put(array[i], array2[i]);
        }
        return h;
    }

这是正确的吗? 接下来我需要将其转换为原始数组。如何做到这一点?

例子:

Map<Integer, String> map = new HashMap<Integer, String>();
Integer[] keys = new Integer[map.size()];
String[] values = new String[map.size()];
int index = 0;
for (Map.Entry<Integer, String> mapEntry : map.entrySet()) {
    keys[index] = mapEntry.getKey();
    values[index] = mapEntry.getValue();
    index++;
}

但是我需要在方法中实现这个功能。如何做到?

而且这还不是全部。我需要将结果包装器数组转换为基本类型。

也许,您可以告诉我如何在您的方法中实现它?

  • 首先:我需要在所有映射方法(哈希映射、树形映射、链接哈希映射)中将两个基本数组转换。
  • 其次:我需要将结果哈希映射转换为我的两个基本数组。

你正在使用哪个版本的Java? - Suresh Atta
那么您就不需要将原始数据类型转换为包装类,可以直接将它们放入映射中。 - Suresh Atta
但是基本类型不受泛型支持。 - Valeriu
声明它,但仍然可以放置一个原始值。 - Suresh Atta
当我使用原始类型时,我将有许多代码。因为我需要实现TreeMap、LinkedHashMap和HashMap。 - Valeriu
2个回答

1

如果你知道你正在使用 int,那很容易。如果你不知道你将使用哪个原始类,解决方案会更加复杂,但并不是非常复杂。

public static void thereAndBack(int[] keys, String[] values) {
    // to map
    Map<Integer, String> map = new HashMap<>();
    for (int i = 0; i < keys.length; i++) {
        // int autobox to Integer
        map.put(keys[i], values[i]);
    }

    // to array
    int[] keys2 = new int[map.size()];
    String[] values2 = new String[map.size()];
    int i = 0;
    for (Entry<Integer, String> entry : map.entrySet()) {
        // Integer autobox to int
        keys2[i] = entry.getKey();
        values2[i] = entry.getValue();
        i++;
    }
}

1
如果我猜得没错的话,您想要一个通用方法,接收一对原始类型数组,并返回一个特定的映射,其键和值与数组相匹配。
此外,您还想要另一个方法,接收一个映射并返回一对原始类型数组,其元素与映射条目相匹配。
如果这些假设是正确的,那么您可以尝试像这样“装箱”您的原始类型:
public static Integer[] box(int[] primitives) {
    return IntStream.of(primitives).boxed().toArray(Integer[]::new);
}

public static Byte[] box(byte[] primitives) {
    return IntStream.range(0, primitives.length).mapToObj(
        i -> primitives[i]).toArray(Byte[]::new);
}

// short, char and boolean left as an exercise

public static Double[] box(double[] primitives) {
    return DoubleStream.of(primitives).boxed().toArray(Double[]::new);
}

public static Float[] box(float[] primitives) {
    return IntStream.range(0, primitives.length).mapToObj(
        i -> primitives[i]).toArray(Float[]::new);
}

public static Long[] box(long[] primitives) {
    return LongStream.of(primitives).boxed().toArray(Long[]::new);
}

然后,您可以按以下方式实现通用的toMap()方法:
public static <K, V, M extends Map<K, V>> M toMap(
    K[] keys, 
    V[] values, 
    Supplier<M> factory) {

    return IntStream.range(0, keys.length).boxed().collect(
        Collectors.toMap(i -> keys[i], i -> values[i], (a, b) -> a, factory));
}

这个函数通过迭代keys和values数组,将每对元素放在factory参数提供的map上,从而将流收集到一个map中。这个factory实际上是一个Supplier,它将被用来创建具体的map实现,比如HashMap、TreeMap、LinkedHashMap等。
请注意,如果map实现不保留插入顺序,比如HashMap,那么您可能会失去元素的顺序。
要进行反向操作,您需要一个辅助类来保存两个数组:
public class Pair<A, B> {

    public Pair(A a, B b) {
        this.a = a;
        this.b = b;
    }

    public final A a;

    public final B b;
}

这是一个简单的键值对容器。然后,您可以按照以下方式将给定的映射转换为一对数组:
public static <K, V, M extends Map<K, V>> Pair<K[], V[]> toArrays(
    M map, 
    IntFunction<K[]> keysFactory,
    IntFunction<V[]> valuesFactory) {

    K[] keys = map.keySet().stream().toArray(keysFactory);
    V[] values = map.values().stream().toArray(valuesFactory);
    return new Pair<>(keys, values);
}

这将通过在给定地图的keySet()和values()集合上进行流处理来创建keys和values数组。分别提供了扮演工厂角色的IntFunction,以使泛型机制按预期工作。否则,您将无法将数组元素的通用类型修复为映射的键和值的通用类型。
在Pair类中,您无法持有原始数组,因为它是通用的,并且(截至2015年9月)仍不允许使用原始类型作为类型参数。
因此,我们需要几个取消装箱方法:
public static int[] unbox(Integer[] wrappers) {
    return Arrays.stream(wrappers).mapToInt(Integer::intValue).toArray();
}

public static float[] unbox(Float[] wrappers) {
    float[] result = new float[wrappers.length];
    IntStream.range(0, wrappers.length).forEachOrdered(
        i -> result[i] = wrappers[i].floatValue());
    return result;
}

// Rest of unbox methods left as an exercise

最后,这里有一个示例展示了如何使用这段代码:

String[] keys = { "one", "two", "three" };
int[] intValues = { 1, 2, 3 };
float[] floatValues = { 1.1f, 2.2f, 3.3f };

Integer[] integers = box(intValues);
Map<String, Integer> map = toMap(keys, integers, HashMap::new);
System.out.println(map); // {one=1, three=3, two=2}

Float[] floats = box(floatValues);
Map<String, Float> map2 = toMap(keys, floats, LinkedHashMap::new);
System.out.println(map2); // {one=1.1, two=2.2, three=3.3}

Pair<String[], Integer[]> arrays = toArrays(map, String[]::new, Integer[]::new);
System.out.println(Arrays.toString(arrays.a)); // [one, three, two]
int[] unboxedInts = unbox(arrays.b);
System.out.println(Arrays.toString(unboxedInts)); // [1, 3, 2]

Pair<String[], Float[]> arrays2 = toArrays(map2, String[]::new, Float[]::new);
System.out.println(Arrays.toString(arrays2.a)); // [one, two, three]
float[] unboxedFloats = unbox(arrays2.b);
System.out.println(Arrays.toString(unboxedFloats)); // [1.1, 2.2, 3.3]

在Java中,浮点数、布尔值、短整型、字符和字节均没有流可用,因此您需要使用一些解决方法。
泛型语法并不是很清晰,但它允许您修复泛型类型,就像我对Map的键和值所做的那样。
最后注意:HashMap不保留插入顺序,而LinkedHashMap则会保留。这解释了map和map2输出之间的差异。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接