2015-10-01 2 views
1

У меня возникают трудности с пониманием HashMap при использовании Object в качестве типа.Хранение объектов нескольких типов в HashMap и их получение

Здесь я создаю два объекта, строку и целое число, которое присваиваю значение. Затем я добавляю этот объект в HashMap. Затем изменяются значения строковых и целочисленных объектов. Но при попытке ссылаться на них, используя HashMap.get(), он показывает исходные значения.

Я предполагаю, что каким-то образом при размещении значений на HashMap создается новый неизменный объект, созданный в экземпляре HashMap вместо связывания исходного исходного объекта?

Вот код:

import java.util.HashMap; 
import java.util.Map; 
public class Test1 { 
    //Create objects 
    static int integ=1; 
    static String strng="Hi"; 
    //Create HashMap 
    static Map<String, Object> objMap = new HashMap(); //Map of shipments 
    public static void main(String[] args) { 
     //Insert objects in HashMap 
     objMap.put("integer", integ); 
     objMap.put("string", strng); 
     //Check the values 
     System.out.println(objMap.get("integer")); 
     System.out.println(objMap.get("string")); 
     //Change values of underlying object 
     integ=2; 
     strng="Bye"; 
     //Check values again 
     System.out.println(objMap.get("integer")); 
     System.out.println(objMap.get("string")); 
    } 
} 

И выход:

debug: 
1 
Hi 
BUILD SUCCESSFUL (total time: 8 seconds) 
+0

См. Http://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value – Benjamin

ответ

2

Когда вы сделаете это:

integ=2; 
    strng="Bye"; 

вы только изменили ссылку на объект не сам объект.

для Integer и String вы не можете изменить объект, как они immutable

так что если вы хотите, чтобы изменить значение в вашей карте, то solutionis:

  1. удалить предыдущие значения из карты.
  2. изменить значения
  3. добавить их к вашей карте
2

Вы изменили значения, но не положил их обратно в HashMap.

integ=2; 
    strng="Bye"; 
    objMap.put("integer", integ); 
    objMap.put("string", strng); 

Я думаю, вы предполагаете, что карта хэша будет ссылаться на измененные значения. Но это не работает, в этом случае, когда вы храните примитивы. Ваше предположение будет хорошо, если вы закроете своих приматов внутри объекта.

т.е.

public class MyClass{ 
    int integ; 
    } 
2

Вам нужно положить ценности снова, так что существующие значения будут переписаны, прежде чем вы получите от карты снова.

public static void main(String[] args) { 
     //Insert objects in HashMap 
     objMap.put("integer", integ); 
     objMap.put("string", strng); 
     //Check the values 
     System.out.println(objMap.get("integer")); 
     System.out.println(objMap.get("string")); 
     //Change values of underlying object 
     integ=2; 
     strng="Bye"; 
     objMap.put("integer", integ); 
     objMap.put("string", strng); 
     //Check values again 
     System.out.println(objMap.get("integer")); 
     System.out.println(objMap.get("string")); 
    } 
2

Я думаю, что вам нужно проверить свои основы Java, поскольку параметры «передаются по значению» в Java.

Это означает, что objMap.put("integer", integ); будет хранить на карте под ключом «целое число» значение integ.

Изменение значения integer после этой операции не повлияет на то, что хранится на карте, так как карта содержит точную копию объекта при .put() времени работы.

Этот подход является противоположностью «pass by reference», где карта будет содержать «указатель на» переменную integ.

1

В этом примере Java использует call-by-value, поэтому сохраняет в HashMap только фактическое значение, а не ссылку. Поэтому, если вы измените значение, вы должны поместить его снова в HashMap.

Надеюсь, это поможет.

1

Вы делаете несколько замешательства. Посмотрите на этот код:

import static org.junit.Assert.assertEquals; 
import static org.junit.Assert.assertNotEquals; 

import java.util.HashMap; 
import java.util.Map; 
import java.util.concurrent.atomic.AtomicInteger; 
import java.util.concurrent.atomic.AtomicReference; 

import org.junit.Before; 
import org.junit.Test; 

// Comment 0) 
public class Test1 { 
    Map<String, Object> objMap = new HashMap<>(); 

    private Integer integ = 1; 
    private String strng = "Hi"; 

    // Comment 1) 
    // private final Integer integ = 1; 
    // private final String strng = "Hi"; 

    // Comment 2) 
    final AtomicInteger integMutable = new AtomicInteger(1); 
    final AtomicReference<String> strngMutable = new AtomicReference<>("Hi"); 

    @Before 
    public void setup() { 
     objMap.put("integer", integ); 
     objMap.put("string", strng); 
     objMap.put("integer2", integMutable); 
     objMap.put("string2", strngMutable); 
    } 

    @Test 
    public void test32886291() { 
     // Comment 1: error raised if fields were final 
     integ = 2; 
     strng = "Bye"; 
     assertNotEquals(2, objMap.get("integer")); 
     assertNotEquals("Bye", objMap.get("string")); 

     integMutable.set(2); 
     strngMutable.set("Bye"); 
     assertEquals(2, ((AtomicInteger) objMap.get("integer2")).intValue()); 
     assertEquals("Bye", objMap.get("string2").toString()); 
    } 
} 

комментарий 0) Прежде всего, я повернул свой класс «Test» в настоящий класс тест с использованием JUnit.

Комментарий 1) Вы, похоже, смущены понятиями «поле», «ссылка», «значение» и «автобоксинг». На карте вы храните объект по ссылке (это то, что вы хотите). Вот почему я впервые заменил ваш int (примитивный тип) Integer (объект).

Когда вы делаете integ = 2, вы не меняете значение этого объекта: вы переустанавливаете поле с именем «integ». Добавление ключевого слова «final» приведет к ошибке («Конечное поле Test1.integ не может быть назначено») и выделите эту точку. Таким образом, изменение значения поля (присвоение ему другого объекта) не влияет на объект, хранящийся на карте. Это подтверждается двумя предложениями assertNotEquals.

Комментарий 2) Невозможно изменить значение Integer и String, которые являются «неизменными». Я заменил их «изменчивыми» объектами, соответственно обертывая значение int и String. Ожидаемое поведение подтверждается двумя предложениями assertEquals.

Смежные вопросы