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[]
считается уникальным, потому что это разные экземпляры, даже если они содержат одинаковые две двойные.
Как я могу это исправить, если мне вообще нужно (есть ли лучший способ)? Мне просто нужна структура данных, которая позволяет мне
- добавлять
doubles[]
- Сохраняет порядок
doubles[]
- Легко перебрать, чтобы получить
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]);
}
}