我正在尝试使用以下数据结构:
//all the words in each file as index, the label as value
static Map< ArrayList<String> , String > train__list_of_file_words = new HashMap<>();
static Map< ArrayList<String> , String > test__list_of_file_words = new HashMap<>();
//frequency count against global dictionary
static Map< int[] , String > train_freq_count_against_globo_dict = new HashMap<>();
static Map< int[] , String > test_freq_count_against_globo_dict = new HashMap<>();
Run Code Online (Sandbox Code Playgroud)
但我被告知这是非感性的,因为它们不能与equals()一起顺利工作并且是可变的.
我想解决方案是编写我自己的对象以类似的方式存储这些信息,但我以前从未这样做过.怎么做?
既然没有人挺身而出,对你的问题给出了完整的答案,我会试一试:
Map< ArrayList<String> , String >这种方法的问题ArrayList<String>是可变的.例如,请参见此示例:
Map<ArrayList<String>, String> map = new HashMap<>();
ArrayList<String> l = new ArrayList<>();
l.add("a");
l.add("b");
map.put(l, "Hello");
System.out.println(map.get(l)); // "Hello";
l.add("c"); // Mutate key.
System.out.println(map.get(l)); // null (value lost!)
Run Code Online (Sandbox Code Playgroud)
进一步阅读:
Map< int[] , String >这是可能的,但可能会令人困惑,因为两个阵列可能看起来相同,但.equals彼此不相同.请考虑以下示例:
Map<int[], String> map = new HashMap<>();
int[] arr1 = { 1, 2 };
map.put(arr1, "Hello");
int[] arr2 = { 1, 2 };
System.out.println(map.get(arr2)); // null, since arr1.equals(arr2) == false
Run Code Online (Sandbox Code Playgroud)
因此,要检索以前插入的值,您需要使用相同的实例作为键.以上示例仅在您使用时有效map.get(arr1).
您可以按照建议滚动自己的数据结构,以跟踪私有数据结构中的映射.例如,您可以使用a Map<List<...>, String>作为支持结构,但要确保您永远不会改变您在该映射中使用的键(例如,通过保持映射为私有而永远不会发布对List-keys的引用).
如果您事先知道密钥的大小,则可以使用嵌套映射,如下所示:Map<String, Map<String, String>>.
您可以使用第三方集合库,例如Guava或Apache Commons.他们有一个名为Tableresp 的数据结构.MultiKeyMap这两者似乎都符合您的要求.
您可以按照@dasblinkenlight的建议创建一个新的,不可变的密钥对象.(提醒一句;这是安全的,因为它String是不可变的!)代码可以略微简化如下:
final class StringTuple {
private String[] vals;
public StringTuple(String... vals) {
this.vals = vals.clone();
}
public int hashCode() {
return Arrays.hashCode(vals);
}
public boolean equals(Object obj) {
return (obj instanceof StringTuple)
&& Arrays.equals(vals, ((StringTuple) obj).vals);
}
}
Run Code Online (Sandbox Code Playgroud)