Как установить пары ключ-значение финала HashMap в Java 11? - PullRequest
0 голосов
/ 11 апреля 2020
import java.util.HashMap;
import java.util.Map;

public class Foo {
    private final Map<String, Integer> exits;

    public Foo() {
        this.exits = new HashMap<>();
    }

    public Map<String, Integer> getExits() {
        return exits;
    }

    public void show() {
        for (String i : exits.keySet()) {
            System.out.println(i + ": " + exits.get(i));
        }
    }
}

class Bar {
    public static void main(String[] args) {
        Foo foo = new Foo();
        foo.getExits().put("A", 1);
        foo.getExits().put("B", 2);
        foo.show();
        //Okay, no problem.
        //Output: A: 1
        //        B: 2
        foo.getExits().replace("A", 10);
        foo.getExits().remove("B");
        foo.show();
        //Output: A: 10
    }
}

Я объявил exits в классе Foo как final, чтобы его нельзя было ссылаться на другой HashMap после назначения в конструкторе. Я также хочу установить все элементы в exits как окончательные, чтобы после того, как я поместил пару ключ-значение в exits, он не может быть изменен или удален каким-либо образом. Я попробовал следующий подход (обратите внимание на изменения в методах getExits() и main()):

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

public class Foo {
    private final Map<String, Integer> exits;

    public Foo(Map<String, Integer> exits) {
        this.exits = exits;
    }

    public Map<String, Integer> getExits() {
        return new HashMap<>(exits);
    }

    public void show() {
        for (String i : exits.keySet()) {
            System.out.println(i + ": " + exits.get(i));
        }
    }
}

class Bar {
    public static void main(String[] args) {
        Map<String, Integer> temp=new HashMap<>();
        temp.put("A", 1);
        temp.put("B", 2);
        Foo foo = new Foo(temp);

        foo.show();
        //Okay, no problem.
        //Output: A: 1
        //        B: 2
        foo.getExits().replace("A", 10);
        foo.getExits().remove("B");
        foo.show();
        //Output: A: 1
        //        B: 2
    }
}

Вопрос 1:
Почему это не сработает, если я объявлю exits as private final Map<final String, final Integer> exits;?
Вопрос 2:
Есть ли другой способ, с помощью которого я могу достичь того же?

PS: Я новичок в Java, так что поправьте меня, если есть какие-либо ошибки, поскольку я могу смешивать понятия C ++ с Java.

Ответы [ 2 ]

1 голос
/ 11 апреля 2020

первый вопрос: на самом деле во втором коде, когда вы каждый раз вызываете getexits, он возвращает другую мелкую копию (новый Hashmap). Мелкая копия - это другая копия выходов, где вы можете изменить только возвращенную карту, а не оригинальную, которую вы объявлено в классе Foo. Итак, foo.getexits () - это совершенно другая карта, которую вы возвращаете, она каждый раз модифицирует новую хэш-карту, а не временную или foo (временную). Если вы кодируете так,

    temp.replace("A",10);
    temp.remove("B");
    foo.show(); 

вместо ,

    foo.getExits().replace("A", 10);
    foo.getExits().remove("B");
    foo.show();

, тогда он напечатает тот же вывод, что и ваша первая программа (он также изменится). Вкратце, ваш второй код не изменяется, потому что каждый раз, когда вы возвращаете и модифицируете новую хэш-карту, которая не имеет отношения к temp.so, это не повлияет на ваш foo (temp).

второй вопрос: если вы действительно хотите чтобы не изменять что-либо в основном классе, вы можете написать следующий код в методе getexits () во второй программе:

  return Collections.unmodifiableMap(exits);

и не изменять ничего во второй программе, как вы. он выдаст

 java.lang.UnsupportedOperationException

всякий раз, когда вы захотите изменить, используя foo.getexits (), и не даст вам изменить это. Но вы все равно можете изменить temp отдельно, так как он не имеет отношения к методу getexits. новичок, как вы, но я постарался ответить на ваш вопрос с моим небольшим знанием. надеюсь, это поможет

1 голос
/ 11 апреля 2020

Ответ 1: Map<final String, final Integer> недопустимый синтаксис в Java. Я не знаю, что вы подразумеваете под этим. Это использование напоминает мне модификатор const в C ++, но final не является константным, и в любом случае String и Integer уже неизменны

Ответ 2: Ваш метод getExits возвращает изменяемую копию карты. Это работает, но чаще всего возвращается неизменяемое представление структуры данных. Это легкий декоратор, который выдает исключение, если вызывающая сторона пытается внести изменения, но в противном случае вызывает методы в исходной карте. Вызывающий должен скопировать саму карту, если он этого хочет.

public Map<String, Integer> getExits() {
    return Collections.unmodifiableMap(exits);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...