Groovy: изменения элементов в одной карте влияют на элементы в копии этой карты - PullRequest
1 голос
/ 05 октября 2019

В функции фильтра я пытаюсь создать отдельную копию хэш-карты и удалить некоторые элементы null из оригинала, однако, наконец, когда я печатаю копию хэш-карты, те же самые элементы удаляются из нее, пока я только этого хочупроизойдет для оригинала, и копия должна остаться без изменений.

Это мой код;

def filter(log){

    Map logCopy = [:]
    logCopy.putAll((log))

    def indexedLog = logCopy.keySet()
    for(def i = 0; i <indexedLog.size(); i++){
        def subIndexedLog = logCopy[indexedLog[i]]
        def subIndexedLogEntrySet = subIndexedLog.keySet();
        for(def j = 0; j <subIndexedLog.size(); j++){ 
            if(subIndexedLog[subIndexedLogEntrySet[j]] == null){
                log[indexedLog[i]].remove(subIndexedLogEntrySet[j])
            }

        }
    }
    println logCopy
    println log
    return log;

}

def log = [letters:[a: null, b: null, c: "c"], numbers: [1: null, 2: null, 3: 3]]
filter(log)

Выход;

[letters:[b:null, c:c], numbers:[2:null, 3:3]]
[letters:[b:null, c:c], numbers:[2:null, 3:3]]

Я так запутался, что когда нулевой элемент удаляется из log в цикле,почему тот же элемент также удаляется из logCopy, и почему b, который действительно имеет значение null, не удаляется. Пожалуйста, помогите мне с этой проблемой, а также, если вы можете предложить лучшее решение, чем моя filter(), сделайте это. Спасибо.

1 Ответ

1 голос
/ 06 октября 2019

Следующий пример поможет понять, что происходит:

    a = [name: "Tom"]
    b = a
    println b.is(a)
    println a
    println b

    a["name"] = "Jerry"
    println a
    println b

    b["name"] = "Mouse"
    println a
    println b

Здесь a и b - две переменные, которые указывают на один и тот же экземпляр объекта. Вот почему любое изменение, сделанное в a, означает также изменение в b и наоборот.

Когда вы копируете карты, то копий объектов не будет, но те же самые экземпляры будут помещены в logCopy. Следующий код для ваших объектов имеет то же объяснение, что и в примере выше:

    log["letters"]["a"] = "123"
    println log    ["letters"]["a"]
    println logCopy["letters"]["a"]

    logCopy["letters"]["a"] = "567"
    println log    ["letters"]["a"]
    println logCopy["letters"]["a"]

Это объясняет, почему ваши изменения на одной карте также видны на другой карте.

Чем отличаются,Карта объектов сама (не их содержимое). Если вы удалите элемент с карты , сам , то вы увидите различия:

    log.remove("numbers")
    println logCopy
    println log

Такое поведение putAll() не является ошибкой. Это то, как это должно работать. Так же, как это работает в Java. Если вы хотите создать копию карты deep , вы должны сделать это вручную: вам нужно перебрать каждую переменную-член, создать их копии, перебрать переменные-члены вложенных объектов и т. Д.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...