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]
我正在开发一个程序,告诉您有关包裹的信息。但是,我在反向依赖方面遇到了一些问题(请参阅评论:检查以前的反向依赖并保存它们)。主要问题是打印时,在将值放入 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]