所以我有一个按照我想要的顺序创建的地图(插入的数据)。 解析映射时,foreach 返回的第一个键不是我插入的第一个键。 有办法实现吗?
对我的地图进行排序也有点棘手,因为它必须按值并在值内的特定字段中排序。 泰
查看 LinkedHashMap 以获取具有可预测迭代顺序的 Map 实现。如果您实际上没有通过键进行查找,您也可以考虑只使用列表。
让我们看看。您的要求似乎是:
没有一个标准的 Java 集合类可以满足所有这些要求。而且我认为 Commons 集合或 Google 集合也不会......
如果您要放弃要求 3,那么
TreeSet
(用自定义 Comparator
实例化)就可以完成这项工作。如果您要放弃要求 4,那么 LinkedHashMap
就可以完成这项工作。
要满足所有要求,您需要执行以下操作之一:
使用
LinkedHashMap
,当您想要根据值以某种顺序进行迭代时,提取地图的 values
集合,使用自定义比较器对其进行排序,然后
返回已排序集合的迭代器。同时使用
LinkedHashMap
和 TreeMap
,并并行更新两者。为
LinkedHashMap
和 TreeMap
创建自定义外观类。当您调用 put
、remove
等时,这需要使两个数据结构保持最新,并且还提供额外的方法来获取排序值。如果您可以通过 value 属性预先对项目进行排序,那么您可以使用
LinkedListHashMap
,因为这会保留您指定的顺序。然而,这似乎有点脆弱,如果您稍后需要向地图添加更多项目,则不适合。
另一种方法是将值存储在列表中,根据需要进行排序,然后使用二分搜索来检索项目并查找新项目的插入点。
您甚至可以将所有这些包装起来并将其放在
Map
界面后面。
Collections 类提供了 binarySearch。概要如下:
List<Value> values
。 Comparable<Value>
类,该类使用要对其进行排序的属性来比较值。 Comparator<Value>
对列表进行排序。Collections.binarySearch(values, aValue, Comparator<Value>)
查找实际值的索引。请注意,aValue 不是真正的值 - 它是一个具有设置为提供键的属性的值,但其余部分未初始化。 aValue 仅用于保存排序键。代码中
List<Value> values = new ArrayList<Values>();
// .. add values
values.add(new Value(key, data1, data2, etc..));
Comparator<Value> compValue = new Comparator<Value>() {
public int compare(Value v1, Value v2) {
return v1.getKey()>v2.getKey();
}
}
Collections.sort(values, compValue);
// now we can search on key
int index = Collections.binarySearch(values, new Value(keyTofind), valueComp);
Value foundValue = null; // value with the key may not be in the list
if (index>=0)
foundValue = values.get(index);
// we can also update the list
Value newValue = new Value(key, data, data2, etc...);
int insert = Collections.binarySearch(values, newValue, valueComp);
// insert will be negative
values.add((-insert)-1, newValue);
编辑:如果您将其包装在地图界面中,例如扩展 AbstractMap,它将是可序列化的。
您可以对地图的entrySet进行排序并将其作为流进行处理。它不会按照添加的顺序返回值,但它允许您控制顺序,这可能比依赖地图更安全
map
.entrySet()
.stream()
.sorted(Entry.comparingByValue(ValueObject::getAttribute))
.forEach(entry -> doSomething(entry));