简体   繁体   English

从 linkedHashMap 分别使用键和值创建新的 Arrays

[英]Create new Arrays from linkedHashMap with keys and values separately

I have a LinkedHashMap and I am trying to split its keys and values and refer to specific key in the keyset or value in valueset.我有一个 LinkedHashMap,我正在尝试拆分它的键和值,并引用键集中的特定键或值集中的值。 For ex.例如。 Lets say I have the folowing LinkedHashMap:假设我有以下 LinkedHashMap:

4 | 4 | 2 2

3 | 3 | 1 1

I want a function to return 1, which is a value at index 1 in the set with values or return 2 for index = 0. And with another function I want to get 3 as value with index 1 in key values.我想要一个 function 返回 1,它是集合中索引 1 处的值,其值为或返回 2,索引 = 0。而另一个 function 我想获得 3 作为键值中索引为 1 的值。 So basically from the LinkedHashMap create an Array with only values/ keys and then look for some given place in this array.所以基本上从 LinkedHashMap 创建一个只有值/键的数组,然后在这个数组中寻找一些给定的位置。 My code looks as follow:我的代码如下所示:

    public static Integer getLHMValue(Map<Integer, Long> lhm, int index) { 
        Set<Map.Entry<Integer, Long>> valueSet = lhm.entrySet();
        Integer[] valueArray = valueSet.toArray(new Integer[valueSet.size()]);
        Integer value = valueArray[index];
        return value;
    }

    public static Integer getLHMKey(Map<Integer, Long> lhm, int index) { 
        Set<Integer> keySet = lhm.keySet();
        Integer[] keyArray = keySet.toArray(new Integer[keySet.size()]);
        Integer key = keyArray[index];
        return key;
}

Though, I get java.lang.ArrayStoreException: java.util.LinkedHashMap$Entry in: Integer[] keyArray = valueSet.toArray(new Integer[valueSet.size()]);.虽然,我得到 java.lang.ArrayStoreException: java.util.LinkedHashMap$Entry in: Integer[] keyArray = valueSet.toArray(new Integer[valueSet.size()]);。 Any ideas?有任何想法吗?

In getLHMValue the problem is your array creation:getLHMValue中,问题是您的数组创建:

Integer[] keyArray = valueSet.toArray(new Integer[valueSet.size()]);

because valueSet is Set<Map.Entry<Integer, Long>> .因为valueSetSet<Map.Entry<Integer, Long>> Modify your initialisation of valueSet tovalueSet的初始化修改为

Collection<Long> valueSet = lhm.values();

But now you get the problem that Collection does not ensure any order.但是现在您遇到了Collection无法确保任何顺序的问题。

Btw: your values are Long so you also should return Long顺便说一句:你的价值观是Long所以你也应该返回Long

Update更新

Firstly, it's highly advisable to favor Collections over Arrays, because collections can offer you behavior and arrays have a type-safety pitfall due to their covariant behavior (refer to "Effective Java" by Joshua Bloch, item "Prefer lists to arrays"). Firstly, it's highly advisable to favor Collections over Arrays, because collections can offer you behavior and arrays have a type-safety pitfall due to their covariant behavior (refer to "Effective Java" by Joshua Bloch, item "Prefer lists to arrays").

Since the map is always the same (clarification provided by OP in the comments) you can declare a list as a stitic final variable, dump map entries into it and access this list from your methods.由于map 始终相同(OP 在评论中提供了说明),您可以将列表声明为stitic final变量,将 map 条目转储到其中并从您的方法中访问此列表。

That would allow to avoid performing unnecessary iteration each method call which costs O(n) time.这将允许避免对每个方法调用执行不必要的迭代,这会花费O(n)时间。

public static final Map<Integer, Long> LHM = // initializing the map
public static final List<Map.Entry<Integer, Long>> ENTRIES = new ArrayList<>(LHM.entrySet());

With that change your methods would work in constant time O(1) instead of linear.通过这种更改,您的方法将在恒定时间O(1)中工作,而不是线性工作。

public static Long getLHMValue(Map<Integer, Long> lhm, int index) {
    
    return ENTRIES.get(index).getValue();
}

public static Integer getLHMKey(Map<Integer, Long> lhm, int index) {

    return ENTRIES.get(index).getKey();
}

You can introduce a variable that would represent the current index.您可以引入一个代表当前索引的变量。

Then iterate over the entries until the target index is reached.然后遍历条目,直到达到目标索引。

Return the key/value from the target entry从目标条目返回键/值

public static Long getLHMValue(Map<Integer, Long> lhm, int index) {
    if (index < 0 || index >= lhm.size()) {
        throw new IllegalArgumentException();
    }
    
    int i = 0;
    Map.Entry<Integer, Long> result = null;
    for (Map.Entry<Integer, Long> entry: lhm.entrySet()) {
        if (i == index) result = entry;
        i++;
    }
    return result.getValue();
}

Alternativelly, you can use Java 11 method Collection.toArray(IntFunction<T[]>) or it's sibling Collection.toArray(T[]) available with earlier versions.或者,您可以使用 Java 11 方法Collection.toArray(IntFunction<T[]>)或其同级Collection.toArray(T[])可用于早期版本。

public static Long getLHMValue(Map<Integer, Long> lhm, int index) {

    return lhm.values().toArray(Long[]::new)[index]; // or lhm.values().toArray(new Long[0])[index];
}

The problem is that the entrySet would be needed to first have an array of Map.Entry s.问题是 entrySet 需要首先有一个Map.Entry数组。 Keeping such an array for both methods would be faster.为这两种方法保留这样的数组会更快。

List<Map.Entry<Integer, Long>> entries = new ArrayList<>(lhm.entrySet());

public static long getLHMValue(Map<Integer, Long> lhm, int index) { 
    return entries.get(index).getValue();
}

public static int getLHMKey(Map<Integer, Long> lhm, int index) { 
    return entries.get(index).getKey();
}

There is no efficient solution if you do it directly, and so it is not advisable to offer these functions to access key and value.如果你直接这样做没有有效的解决方案,因此不建议提供这些函数来访问 key 和 value。

public static Long getLHMValue(Map<Integer, Long> lhm, int index) { 
    return lhm.entrySet().stream()
        .map(Map.Entry<Integer, Long>::getValue)
        .skip(index)
        .findFirst()
        .orElseThrow(IndexOutOfBoundsException::new);
}

public static Integer getLHMKey(Map<Integer, Long> lhm, int index) { 
    return lhm.entrySet().stream()
        .map(Map.Entry<Integer, Long>::getKey)
        .skip(index)
        .findFirst()
        .orElseThrow(IndexOutOfBoundsException::new);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM