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

Java HashMap stores values in keys not intended

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

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 passes 按值传递对象引用。当您将 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]