LinkedHashMap<double [], Integer>, не может получить доступ к Integer с помощью.get или.containsKey

У меня есть серия небольших массивов (состоящих из двух двойных), многие из которых одинаковы. Например

{5.0, 15.0}
{5.0, 15.0}
{5.0, 15.0}
{12.0, 8.0}
{10.0, 8.0}
{10.0, 8.0}

Я хочу иметь возможность подсчитать количество каждого массива, т.е.

3 of {5.0, 15.0}
1 of {12.0, 8.0}
2 of {10.0, 8.0}

Чтобы сделать это, я попытался использовать LinkedHashMap (связанный, потому что заказ может вступить в силу позже):

import java.util.Map;
import java.util.LinkedHashMap;

public class MapArrayInt {
        Map<double[], Integer> arrays = new LinkedHashMap<double[], Integer>();

    public static void main(String[] args) {
        MapArrayInt mapArrayInt = new MapArrayInt();
        mapArrayInt.addArray(5.0, 15.0);
        mapArrayInt.addArray(5.0, 15.0);
        mapArrayInt.addArray(5.0, 15.0);
        mapArrayInt.addArray(12.0, 8.0);
        mapArrayInt.addArray(10.0, 8.0);
        mapArrayInt.addArray(10.0, 8.0);
        System.out.println(String.valueOf(mapArrayInt.arrays.get(new double[]{5.0, 15.0})));
        System.out.println(String.valueOf(mapArrayInt.arrays.get(new double[]{12.0, 8.0})));
        System.out.println(String.valueOf(mapArrayInt.arrays.get(new double[]{10.0, 8.0})));
    }

    void addArray(double val1, double val2) {
        double[] newArray = new double[]{val1, val2};
        if (!arrays.containsKey(newArray)) {
            arrays.put(newArray, 1);
        } else {
            arrays.put(newArray, arrays.get(newArray) + 1);
        }
    }
}

Я ожидал этого выхода,

3
1
2

но получил,

null
null
null

Я довольно новичок в Java, но я подозреваю, что это может быть потому, что каждый double[] считается уникальным, потому что это разные экземпляры, даже если они содержат одинаковые две двойные.

Как я могу это исправить, если мне вообще нужно (есть ли лучший способ)? Мне просто нужна структура данных, которая позволяет мне

  1. добавлять doubles[]
  2. Сохраняет порядок doubles[]
  3. Легко перебрать, чтобы получить doubles[] и номер сказал doubles[]

2 ответа

Решение

Как я уже сказал в своем комментарии, с new вы создаете новый экземпляр объекта. Это означает, что массивы, которые вы добавили mapArrayInt.addArray(5.0, 15.0); и массивы в mapArrayInt.arrays.get(new double[]{5.0, 15.0}) ссылаться на разные объекты. Вот почему вы получаете nullпотому что для карты это разные ключи.

Чтобы обойти это, вы можете создать собственный класс-оболочку

import java.util.Arrays;
public class Exercise {
    private final double[] array;
    public Exercise(double first, double second) {
        this.array = new double[]{first, second};
    }

    public boolean equals(Object obj) {
        if(!(obj instanceof Exercise)) {
            return false;
        }
        Exercise other = (Exercise)obj;
        return Arrays.equals(this.array, other.array);
    }

    public int hashCode() {
        return Arrays.hashCode(array);
    }
}

equals а также hashCode методы важны, когда вы хотите использовать этот класс в коллекциях, таких как Mapв противном случае хеш-код Object используется для проверки равенства, и у вас будет та же проблема, что и сейчас.

Затем в вашем основном классе вы можете использовать его так:

void addArray(double val1, double val2) {
    Exercise exercise = new Exercise(val1, val2);
    if (!arrays.containsKey(exercise)) {
        arrays.put(exercise, 1);
    } else {
        arrays.put(exercise, arrays.get(exercise) + 1);
    }
}

А также System.out.println(String.valueOf(mapArrayInt.arrays.get(new Exercise(5.0, 15.0))));

РЕДАКТИРОВАТЬ: я изменил один из двойников на int (вы сказали, что вы представляете повторения и вес... и повторы могут быть только натуральным числом, верно?)

Вы можете создать создать Exercise-Class, как показано ниже, и использовать статический метод "of" для создания экземпляров:

package somepackage;

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;

public class Exercise
{
    private static final Map<Integer, Map<Double, WeakReference<Exercise>>> instances = new HashMap<>();

    private final int reps;
    private final double weight;

    private Exercise(int reps, double weight)
    {
        this.reps = reps;
        this.weight = weight;
    }

    public static Exercise of(int reps, double weight)
    {
        if (!instances.containsKey(reps))
        {
            instances.put(reps, new HashMap<>());
        }

        Map<Double, WeakReference<Exercise>> innerMap = instances.get(reps);
        WeakReference<Exercise> weakRef = innerMap.get(weight);
        Exercise instance = null;

        if (weakRef != null)
        {
            instance = weakRef.get();
        }

        if (weakRef == null || instance == null || weakRef.isEnqueued())
        {
            instance = new Exercise(reps, weight);
            innerMap.put(weight, new WeakReference<>(instance));
        }

        return instance;
    }

    public int getReps()
    {
        return this.reps;
    }

    public double getWeight()
    {
        return this.weight;
    }
}

И тогда вы можете поместить эти упражнения в карту, как показано ниже:

public void addArray(int reps, double weight)
{
    Exercise exercise = Exercise.of(reps, weight);
    if (!arrays.containsKey(exercise))
    {
        arrays.put(exercise, 1);
    }
    else
    {
        arrays.put(exercise, arrays.get(exercise) + 1);
    }
}

ИЛИ: вместо double[] в качестве ключа вы можете использовать Map<Double, Integer> как ваше значение для 2 значений:

package somepackage;

import java.util.HashMap;
import java.util.Map;

public class MapArrayInt
{
    private final Map<Double, Map<Double, Integer>> values;

    public MapArrayInt()
    {
        this.values = new HashMap<>();
    }

    public void addArray(double val1, double val2)
    {
        if (!this.values.containsKey(val1))
        {
            this.values.put(val1, new HashMap<>());
        }

        Map<Double, Integer> innerValues = this.values.get(val1);
        if (innerValues.containsKey(val2))
        {
            innerValues.put(val2, innerValues.get(val2) + 1);
        }
        else
        {
            innerValues.put(val2, 1);
        }
    }

    public int getArrayValue(double val1, double val2)
    {
        Map<Double, Integer> innerValues = this.values.get(val1);
        if (innerValues == null)
        {
            // you may also throw an Exception here
            return 0;
        }

        Integer value = innerValues.get(val2);
        if (value == null)
        {
            // also here you may throw an Exception
            return 0;
        }

        return value;
    }

    public int getArrayValue(double[] values)
    {
        return getArrayValue(values[0], values[1]);
    }
}
Другие вопросы по тегам