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

Java HashMap将值存储在非预期的键中,java,ubuntu,intellij-idea,hashmap,key,Java,Ubuntu,Intellij Idea,Hashmap,Key,我正在做一个程序,告诉你关于一个包的信息。但是,我在反向依赖项方面遇到了一些问题(请参见“注释:检查以前的反向依赖项并保存它们”)。主要问题是,在将值放入HashMap之后,在打印时,它似乎以正确的方式存储它们。但是,在完成该过程后打印映射的键和值会返回其他值。编码后可以看到打印的信息 public class MainActivity { public static void main (String[] args) { ArrayList<String>

我正在做一个程序,告诉你关于一个包的信息。但是,我在反向依赖项方面遇到了一些问题(请参见“注释:检查以前的反向依赖项并保存它们”)。主要问题是,在将值放入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");
        }

   }
} 
似乎要存储的值不是进程结束时打印的值。

问题 Java按值传递对象引用。当您将
列表
currentRevDependencies
放入
revDependencies
映射
时,
映射
中存储的不是
列表
的副本,而仅仅是对象引用。当外部更改
currentRevDependencies
时(如您在其上调用
clear
),映射内的列表将更改。这意味着对于在while循环的一次迭代中添加的所有键,
列表
引用将是相同的,从而导致您观察到的重复值

如何修复它 要解决此问题,请为放入
映射
的每个键值对创建一个新的
列表
,而不是每次清除最后一个
映射
,如下所示:

//[...]
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);
//[...]
问题 Java按值传递对象引用。当您将
列表
currentRevDependencies
放入
revDependencies
映射
时,
映射
中存储的不是
列表
的副本,而仅仅是对象引用。当外部更改
currentRevDependencies
时(如您在其上调用
clear
),映射内的列表将更改。这意味着对于在while循环的一次迭代中添加的所有键,
列表
引用将是相同的,从而导致您观察到的重复值

如何修复它 要解决此问题,请为放入
映射
的每个键值对创建一个新的
列表
,而不是每次清除最后一个
映射
,如下所示:

//[...]
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);
//[...]

很高兴我能帮忙,欢迎来到Stackoverflow!为了将来的参考,你应该考虑用A。如果不是因为我有一个linux系统,我自己找一个示例文件,我就帮不了你。很高兴我能帮上忙,欢迎来到Stackoverflow!为了将来的参考,你应该考虑用A。如果不是因为我有一个linux系统,我自己找一个示例文件,我就帮不了你。
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]