HashMap Keys 和 Value 比较

HashMap Keys and Value comparison

我正在将 HashMap 值与键进行比较,如果键较大则进行替换。目的是更新和弦系统模拟的手指Table。

我有 HashMap 数据:

Key 0 with Values: [1,2,4,8,16]
Key 3 with Values: [4,5,7,11,19]
Key 7 with Values: [8,9,11,15,23]

期望的结果是,对于每个键 0、3 和 7,其值将与下一个键值进行比较。

Example:
For key 0, compare its values with next key value which is 3.
3 compare with [1,2,4,8,16] and replace 1,2 with 3 because 3 > 1 and 2

For key 3, compare its values with next key value which is 7.
7 compare with [4,5,7,11,19] and replace 4,5 with 7 because 7 > 4 and 5

下面编写的代码执行以下操作:

For the first set of values [1,2,4,8,16]
1 compare with [0] 
2 compare with [0]
4 compare with [0]
etc.. and it moves on to another set of values

[4,5,7,11, 19]

4 compare with [3]
5 compare with [3]
7 compare with [3]

如何修改代码以达到上述预期结果?

public void updateFingerTable() {

        chordSize = chord.initChordSize;

        for (Map.Entry<Integer, node> m : peerList.entrySet()) {

            for (int i=0; i<chordSize; i++) {

                System.out.println("Successor i: " + m.getValue().successor[i]);
                System.out.println ("Key: " + m.getKey());

                if (m.getValue().successor[i] < m.getKey()) {

                    m.getValue().successor[i] = m.getKey();
                    //System.out.println(m.getValue().successor[i]);
                }
            }

首先,您似乎做出了(错误的!)假设 HashMap 有序的

不是这样的!

如果您想要一个按其键值排序的映射,则必须使用 TreeMap。 (或者,您可以从地图中收集所有条目,并将它们放入一个列表中,然后您可以根据它们的键对列表进行排序)。

除此之外,确定映射中的 "next" 键并不是那么简单。 (事实上​​ ,对于 TreeMap,您可以使用 higherKey method,但这在这里不是必需的)。

您可以简单地遍历条目,并始终参考更新列表的 previous 条目(基于 current条目)。

import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;

public class KeyValueListTest
{
    public static void main(String[] args)
    {
        Map<Integer, IntArrayNode> map = new TreeMap<Integer, IntArrayNode>();
        map.put(0, new IntArrayNode(new int[]{1,2,4,8,16}));
        map.put(3, new IntArrayNode(new int[]{4,5,7,11,19}));
        map.put(7, new IntArrayNode(new int[]{8,9,11,15,23}));

        System.out.println("Before update:");
        for (Map.Entry<Integer, IntArrayNode> e : map.entrySet()) 
        {
            System.out.println(e);
        }

        update(map);

        System.out.println("After update:");
        for (Map.Entry<Integer, IntArrayNode> e : map.entrySet()) 
        {
            System.out.println(e);
        }
    }

    private static void update(IntArrayNode node, int minValue)
    {
        for (int i=0; i<node.getNumElements(); i++)
        {
            node.setElement(i, Math.max(minValue, node.getElement(i)));
        }
    }

    public static void update(Map<Integer, IntArrayNode> map) 
    {
        Map.Entry<Integer, IntArrayNode> previous = null;
        for (Map.Entry<Integer, IntArrayNode> e : map.entrySet()) 
        {
            if (previous != null)
            {
                update(previous.getValue(), e.getKey());
            }
            previous = e;
        }
    }
}


class IntArrayNode
{
    private final int elements[];

    IntArrayNode(int elements[])
    {
        this.elements = elements.clone();
    }

    int getNumElements()
    {
        return elements.length;
    }

    int getElement(int index)
    {
        return elements[index];
    }
    void setElement(int index, int value)
    {
        elements[index] = value;
    }
    @Override
    public String toString()
    {
        return Arrays.toString(elements);
    }
}

对于您的示例输入,这将打印

Before update:
0=[1, 2, 4, 8, 16]
3=[4, 5, 7, 11, 19]
7=[8, 9, 11, 15, 23]

After update:
0=[3, 3, 4, 8, 16]
3=[7, 7, 7, 11, 19]
7=[8, 9, 11, 15, 23]

我看到两个问题,乍一看似乎违反了您示例的逻辑。

根据您的示例,当前元素的映射值必须与 下一个 元素的映射键进行比较,而不是 当前

  1. 首先,与 for (int i=0; i<chordSize; i++) { 一致:我期待您会遍历 m.getValue().length() 以便您可以迭代与 [= 关联的值11=],而不是 chordSize,它似乎与此地图有关,但我不确定为什么。

  2. 其次,符合 if (m.getValue().successor[i] < m.getKey()) { 我认为您需要将 m.getValue().successor[i]next 元素的键进行比较,而不是 当前元素的键。

考虑到这一点,您需要将所有地图项放入另一个数据结构中,该数据结构为您提供基于索引的访问(数组似乎没问题,因为您已经知道地图的大小)到其组件,以便您将能够获取下一个地图项,同时还可以使用当前地图项。这将使比较变得更加容易。

希望对您有所帮助。

您可以将 value 视为可以使用 ArrayList 和 key 实现的 Integer 动态数组,因为 Integer.You 可以针对您的目的编写如下代码:

List<Integer> value=new ArrayList<>();
       for (Map.Entry pair : map.entrySet()) 
       {

        Integer key=(Integer)pair.getKey();
        for(Integer x:(ArrayList<Integer>)(pair.getValue()))
        {
            if(key>x)
            {
                value.add(key);
            }
            else
            {
                value.add(x);
            }

        }
        map.put(key, (ArrayList<Integer>) value);
        System.out.println(value);
        value=new ArrayList<>();

    }

恐怕你的例子还是有点不清楚。以下是您想执行的操作:

3 keys [0,3,7] 
Three sets of values: [1,2,4,8,16], [4,5,7,11,19], [8,9,11,15,23]

Step 1):

You take the 0 from the keys and compare it with the values: 
0 > 1? No ... 0>16? No.

Step 2): 

Compare the 3 from the keys with the values: 
3>1? Yes -> Replace 1 with 3 ... 3>16? No ... 

Step 3):

Compare the 7 from the keys with the values:
7>1 Yes -> Replace 1 with 7, 7>2? Yes -> Replace...

如果是,为什么还要比较小的键呢?键 7 将 "override" 0 和 3 之前所做的所有更改,因此只需找到最大的键并将其与值进行比较即可。

int keyArray[] = new int[]{0,3,7};

int largest = keyArray[0];

for(int i=1; i< keyArray.length; i++)
{
if(keyArray[i] > largest)
    largest = keyArray[i];                       
}

然后您可以查看您的值集并将它们与 largest.equals() 与 HashMap 进行比较。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

public class Test {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Map<Integer, List<Integer>> hash = new HashMap<Integer,List<Integer>>();
        List<Integer> list1 = new ArrayList<Integer>();
        list1.add(1);list1.add(2);list1.add(4);list1.add(8);list1.add(16);
        List<Integer> list2 = new ArrayList<Integer>();
        list2.add(4);list2.add(5);list2.add(7);list2.add(11);list2.add(19);
        List<Integer> list3 = new ArrayList<Integer>();
        list3.add(8);list3.add(9);list3.add(11);list3.add(15);list3.add(23);
        hash.put(0,list1);
        hash.put(3,list2);
        hash.put(7,list3);

        System.out.println("Input:");
        for (Map.Entry<Integer, List<Integer>> m1 : hash.entrySet()) {
            System.out.println("Successor i: " + m1.getValue());
            System.out.println ("Key: " + m1.getKey());
        } 

        Map<Integer, List<Integer>> out = hash;
        List<Integer> list = new ArrayList<Integer>();
        int keyValue = 0;
        int count=0;
        for (Entry<Integer, List<Integer>> m : hash.entrySet()) {

            if(count==0){
                list = m.getValue();
                keyValue = m.getKey();
                count++;
                continue;
            }
            else{

                for(int i=0;i<list.size();i++){
                    if(m.getKey()>list.get(i)){
                        list.set(i, m.getKey());
                    }
                }
                out.put(keyValue,list);
                list = m.getValue();
                keyValue = m.getKey();
            }


        }

        System.out.println("Output:----------------");
        for (Map.Entry<Integer, List<Integer>> m1 : out.entrySet()) {
            System.out.println("Successor i: " + m1.getValue());
            System.out.println ("Key: " + m1.getKey());
        } 

    }

}