【问题标题】:Java HashMap stores values in keys not intendedJava HashMap 将值存储在非预期的键中
【发布时间】:2020-08-19 08:33:51
【问题描述】:

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

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 ubuntu intellij-idea hashmap key


    【解决方案1】:

    问题

    Java 按值传递对象引用。当您将List currentRevDependencies 放入您的revDependencies Map 时,存储在Map 中的不是List 的副本,而只是一个对象引用。当currentRevDependencies 在外部更改时(就像您在上面调用clear),地图内的列表会更改。这意味着对于在一次 while 循环中添加的所有键,List 引用将相同,从而导致您观察到重复值。

    如何解决

    要解决此问题,请为您放入 Map 的每个键值对创建一个新的 List,而不是像这样每次都清除最后一个 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]
    

    【讨论】:

    • 很高兴我能提供帮助,欢迎来到 Stackoverflow!为了将来参考,您应该考虑使用minimal, reproducible example 询问。如果不是我自己有一个 linux 系统自己找一个示例文件,我就帮不了你。
    猜你喜欢
    • 2012-06-18
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多