Java HashMap 将值存储在非预期的键中

标签 java ubuntu intellij-idea hashmap key

我正在开发一个程序,该程序会告诉您有关包裹的信息。但是,我在反向依赖方面遇到了一些问题(请参阅评论下:检查以前的反向依赖并保存它们)。主要问题是打印时,在将值放入 HashMap 之后,它似乎以正确的方式存储它们。然而,在完成该过程后打印 map 的键和值会返回其他值。打码后可以看到打印的信息。

public class MainActivity {
    public static void main (String[] args) {
        ArrayList<String> packages = new ArrayList<String>();
        ArrayList<String> descriptions = new ArrayList<String>();
        HashMap<String, ArrayList<String>> dependencies = new HashMap<>();
        HashMap<String, ArrayList<String>> revDependencies = new HashMap<>();
        int i = 0;
        String packageStart = "Package:";
        String descriptionStart = "Description:";
        String dependenciesStart = "Depends:";

        String packageName = "";

        BufferedReader reader;
        try {
            reader = new BufferedReader(new FileReader(
                    "/var/lib/dpkg/status"));
            String line = reader.readLine();
            while (line != null) {
                //System.out.println(line);

                if (line.startsWith(packageStart)) {
                    packageName = line.substring(packageStart.length()).trim();
                    packages.add(packageName);
                }
                if (line.startsWith(descriptionStart)) {
                    descriptions.add(line.substring(descriptionStart.length()).trim());
                }
                if (line.startsWith(dependenciesStart)) {
                    String subline = line.substring(dependenciesStart.length());
                    String[] dependenciesWithVersion = subline.split(", ");
                    ArrayList<String> dependenciesWOVersion = new ArrayList<String>();
                    ArrayList<String> currentRevDependencies = new ArrayList<String>();
                    String currentDependency;

                    for (String dependencyWithVersion : dependenciesWithVersion) {
                        int index = dependencyWithVersion.indexOf("(");
                        currentRevDependencies.clear();

                        //Take the version out of the package name
                        if (index != -1) {
                            currentDependency = dependencyWithVersion.substring(0, index);
                        } else {
                            currentDependency = dependencyWithVersion;
                        }
                        currentDependency.trim();
                        dependenciesWOVersion.add(currentDependency);

                        
                        //Check for previous reverse dependencies and save them
                        if (revDependencies.get(currentDependency) != null){
                            currentRevDependencies = revDependencies.get(currentDependency);
                        }

                        currentRevDependencies.add(packageName);
                        revDependencies.put(currentDependency, currentRevDependencies);

                        System.out.print("Package: " + packageName + " Dependency: " + currentDependency + " RevDepencencies: " + revDependencies.get(currentDependency) +  "\n");
                    }
                    dependencies.put(packageName, dependenciesWOVersion);

                    if (i == 2){
                        break;
                    }
                    i++;
                }
                line = reader.readLine();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        for (String key : revDependencies.keySet()){
            System.out.print(key + " " + revDependencies.get(key) + "\n");
        }

   }
} 
屏幕上打印以下内容:
Package: accountsservice Dependency:  dbus RevDepencencies: [accountsservice]
Package: accountsservice Dependency: libaccountsservice0  RevDepencencies: [accountsservice]
Package: accountsservice Dependency: libc6  RevDepencencies: [accountsservice]
Package: accountsservice Dependency: libglib2.0-0  RevDepencencies: [accountsservice]
Package: accountsservice Dependency: libpolkit-gobject-1-0  RevDepencencies: [accountsservice]
Package: acl Dependency:  libacl1  RevDepencencies: [acl]
Package: acl Dependency: libc6  RevDepencencies: [accountsservice, acl]
Package: acpi-support Dependency:  acpid  RevDepencencies: [acpi-support]

acpid  [acpi-support]
libaccountsservice0  [accountsservice, acl]
libpolkit-gobject-1-0  [accountsservice, acl]
libglib2.0-0  [accountsservice, acl]
libc6  [accountsservice, acl]
dbus [accountsservice, acl]
libacl1  []
似乎正在存储的值不是过程完成时打印的值。

最佳答案

问题
Java 按值传递对象引用。当你把 List currentRevDependencies进入您的revDependencies Map ,存储在 Map 中的内容不是 List 的副本但仅仅是一个对象引用。当currentRevDependencies被外部更改(就像您在其上调用 clear 一样), map 内的列表会更改。这意味着对于在一次 while 循环中添加的所有键,List引用将是相同的,导致您观察到的重复值。
如何修复它
要解决此问题,请创建一个新的 List对于您放入 Map 的每个键值对而不是清除最后一个 Map每次都是这样:

//[...]
String subline = line.substring(dependenciesStart.length());
String[] dependenciesWithVersion = subline.split(", ");
ArrayList<String> dependenciesWOVersion = new ArrayList<String>();
String currentDependency;

for (String dependencyWithVersion : dependenciesWithVersion) {
    ArrayList<String> currentRevDependencies = new ArrayList<String>(); // <- instantiate new list each iteration

    //[...]

    revDependencies.put(currentDependency, currentRevDependencies);
}
dependencies.put(packageName, dependenciesWOVersion);
//[...]
输出:
Package: libasan0 Dependency:  gcc-4.8-base  RevDepencencies: [libasan0]
Package: libasan0 Dependency: libc6  RevDepencencies: [libasan0]
Package: libasan0 Dependency: libgcc1  RevDepencencies: [libasan0]
Package: libasan0 Dependency: libstdc++6  RevDepencencies: [libasan0]
Package: libvorbisfile3 Dependency:  libc6  RevDepencencies: [libvorbisfile3]
Package: libvorbisfile3 Dependency: libogg0  RevDepencencies: [libvorbisfile3]
Package: libvorbisfile3 Dependency: libvorbis0a  RevDepencencies: [libvorbisfile3]
Package: libquadmath0 Dependency:  gcc-4.9-base  RevDepencencies: [libquadmath0]
Package: libquadmath0 Dependency: libc6  RevDepencencies: [libasan0, libquadmath0]
 libc6  [libvorbisfile3]
libvorbis0a  [libvorbisfile3]
 gcc-4.9-base  [libquadmath0]
libgcc1  [libasan0]
libc6  [libasan0, libquadmath0]
libstdc++6  [libasan0]
 gcc-4.8-base  [libasan0]
libogg0  [libvorbisfile3]

关于Java HashMap 将值存储在非预期的键中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63483054/

相关文章:

java - 使用Java映射/列表按类似结构分组

java - 在带有空格的数组中搜索元素

java - 在 jdbc sql server 连接中更改数据库

java - 空对象还是虚拟对象?

ubuntu - 使用 cmake 的 Libhand 库编译错误

ubuntu - linux下安装软件的区别

shell - GnuPG Shell 脚本 - 拒绝读取密码

kotlin - 无法将 kotlinx 添加到新的 Kotlin/JS 项目中

java - 使用 IntelliJ 从 PropertiesLoader 加载的 Spring Boot 模块时出现 NoClassDefFoundError

java - Java反编译获取重复的局部变量