如何制作一个新的 HashMap 且不会更改我从中复制的 HashMap?

发布于 2025-01-13 13:37:26 字数 815 浏览 2 评论 0原文

我有一个称为项目数据库的 HashMap,它存储有关所有项目的数据。

然而,这些项目可以有修饰符(在这种情况下,统计乘数很重要)。每当我将一个项目更改为一个特定项目时,它最终会更改 HashMap 中的基本项目。

例如,每当玩家创建武士刀时,它都会执行类似的操作。

HashMap<String, CustomItem> db = new HashMap<String, CustomItem>();
db.putAll(ItemDatabase.database);
CustomItem ci = db.get("KATANA");

从那里开始,通过 CustomItem ci 上的 getBukkitItem 函数应用修改器,基本上是乘以该 CustomItem 上的大量统计数据并应用它。

baseHealth = (int) ((abbaseHealth / 100.0) * multiplier);

和其他类似的统计数据。

但是,每当我对这个新的 CustomItem 进行更改时,它也适用于 ItemDatabase 哈希图。这意味着每当有人制作另一个武士刀时,这些相乘的统计数据就会成为要相乘的新基本统计数据。

TL;DR 每当我更改从 HashMap (db) 获得的变量时,该更改也适用于 HashMap (itemdb)。即使它来自的 HashMap (db) 是另一个 HashMap (itemdb) 的副本,也会发生这种情况

我已经尝试了上面的方法,并在 HashMap 上使用 .clone() 并将其转换回 HashMap。不幸的是我不太确定还能尝试什么。

I have a HashMap called the Item Database, which stores data about all of the items.

However, these items can have modifiers (in this case, the stat multiplier is important). Whenever I change an item to just one specific item drop, it ends up changing the base item from the HashMap.

For example, whenever a player creates a Katana, it does something like this.

HashMap<String, CustomItem> db = new HashMap<String, CustomItem>();
db.putAll(ItemDatabase.database);
CustomItem ci = db.get("KATANA");

From there, modifiers are applied via a getBukkitItem function on the CustomItem ci, basically multiplying a lot of the stats on that CustomItem and applying it.

baseHealth = (int) ((abbaseHealth / 100.0) * multiplier);

and other stats like that.

However, whenever I make changes to this new CustomItem, it also applies to the ItemDatabase hashmap. This means that whenever somebody makes another Katana, those multiplied stats become the new base stats to be multiplied.

TL;DR Whenever I'm changing a variable I got from a HashMap (db), that change also applies to the HashMap (itemdb). This happens even if the HashMap (db) it's from, is a copy of another HashMap (itemdb)

I have tried the method above, and using .clone() on a HashMap and casting it back to HashMap. Unfortunately I'm not really sure what else to try.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

郁金香雨 2025-01-20 13:37:26

您应该创建一个深度克隆的新对象。使用 orika 框架如下。

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

@Test
public void t() {

    Map<Integer, User> map = new HashMap<>();

    User one = new User();
    one.setName("one");

    System.out.println(one);
    User two = new User();
    two.setName("two");

    System.out.println(two);
    map.put(1,one);
    map.put(2,two);



    TypeBuilder<Map<Integer,User>> typeBuilder = new TypeBuilder<Map<Integer,User>>() {

    };
    Type<Map<Integer,User>> type = typeBuilder.build();
    Map<Integer,User> copyMap = mapperFactory.getMapperFacade().mapAsMap(map, type,type);

    System.out.println(copyMap.get(1));
    System.out.println(copyMap.get(2));

}

you should create a new object of deep clone. Using orika framework like below.

MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

@Test
public void t() {

    Map<Integer, User> map = new HashMap<>();

    User one = new User();
    one.setName("one");

    System.out.println(one);
    User two = new User();
    two.setName("two");

    System.out.println(two);
    map.put(1,one);
    map.put(2,two);



    TypeBuilder<Map<Integer,User>> typeBuilder = new TypeBuilder<Map<Integer,User>>() {

    };
    Type<Map<Integer,User>> type = typeBuilder.build();
    Map<Integer,User> copyMap = mapperFactory.getMapperFacade().mapAsMap(map, type,type);

    System.out.println(copyMap.get(1));
    System.out.println(copyMap.get(2));

}
爱,才寂寞 2025-01-20 13:37:26

您需要创建新的 CustomItem 实例。如果您只制作地图的副本,则只是复制地图中存储的引用;他们仍然会引用相同的 CustomItem 实例。

您可以通过向 CustomItem 添加复制构造函数或 clone() 方法来简化此操作。复制构造函数的示例:

public class CustomItem {
    public CustomItem(CustomItem other) {
        this.name = other.name;
        this.baseHealth = other.baseHealth;
        this.multiplier = other.multiplier;
        // Don't want two instances to refer to the same List!
        this.inventoryList = new ArrayList<>(other.inventoryList);
        // etc.
    }
}

clone() 方法的示例:

public class CustomItem
implements Cloneable {

    @Override
    public CustomItem clone()() {
        try {
            CustomItem copy = (CustomItem) super.clone();

            // Don't want two instances to refer to the same List!
            copy.inventoryList = new ArrayList<>(copy.inventoryList);
            // etc.

            return copy;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }
}

一旦您找到了复制 CustomItem 实例的方法,您就需要在新的 Map 中使用它:

Map<String, CustomItem> newMap = new HashMap<>();

for (Map.Entry<String, CustomItem> entry : db) {
    String key = entry.getKey();
    CustomItem value = entry.getValue()

    value = value.clone();

    newMap.put(key, value);
}

更短的方法:

Map<String, CustomItem> newMap = new HashMap<>(db);
newMap.replaceAll((k, v) -> v.clone());

You need to make new CustomItem instances. If you only make a copy of the Map, you’re just copying the references stored in the Map; they’ll still refer to the same CustomItem instances.

You can make this easier by adding a copy constructor or clone() method to CustomItem. Example of a copy constructor:

public class CustomItem {
    public CustomItem(CustomItem other) {
        this.name = other.name;
        this.baseHealth = other.baseHealth;
        this.multiplier = other.multiplier;
        // Don't want two instances to refer to the same List!
        this.inventoryList = new ArrayList<>(other.inventoryList);
        // etc.
    }
}

Example of a clone() method:

public class CustomItem
implements Cloneable {

    @Override
    public CustomItem clone()() {
        try {
            CustomItem copy = (CustomItem) super.clone();

            // Don't want two instances to refer to the same List!
            copy.inventoryList = new ArrayList<>(copy.inventoryList);
            // etc.

            return copy;
        } catch (CloneNotSupportedException e) {
            throw new RuntimeException(e);
        }
    }
}

Once you have a way to copy CustomItem instances, you need to use it in your new Map:

Map<String, CustomItem> newMap = new HashMap<>();

for (Map.Entry<String, CustomItem> entry : db) {
    String key = entry.getKey();
    CustomItem value = entry.getValue()

    value = value.clone();

    newMap.put(key, value);
}

A shorter way:

Map<String, CustomItem> newMap = new HashMap<>(db);
newMap.replaceAll((k, v) -> v.clone());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文