我如何按照创建地图(JAVA)的相同顺序解析地图(foreach)

问题描述 投票:0回答:4

所以我有一个按照我想要的顺序创建的地图(插入的数据)。 解析映射时,foreach 返回的第一个键不是我插入的第一个键。 有办法实现吗?

对我的地图进行排序也有点棘手,因为它必须按值并在值内的特定字段中排序。 泰

java dictionary sorting foreach
4个回答
6
投票

查看 LinkedHashMap 以获取具有可预测迭代顺序的 Map 实现。如果您实际上没有通过键进行查找,您也可以考虑只使用列表。


4
投票

让我们看看。您的要求似乎是:

  1. 您有一组键/值对,其中键是唯一的。
  2. 您希望能够快速查找给定键的值。
  3. 您希望能够按插入顺序迭代键(或键对)。
  4. 您希望能够按照值类型的某些字段的顺序迭代值。

没有一个标准的 Java 集合类可以满足所有这些要求。而且我认为 Commons 集合或 Google 集合也不会......

如果您要放弃要求 3,那么

TreeSet
(用自定义
Comparator
实例化)就可以完成这项工作。如果您要放弃要求 4,那么
LinkedHashMap
就可以完成这项工作。

要满足所有要求,您需要执行以下操作之一:

  • 使用

    LinkedHashMap
    ,当您想要根据值以某种顺序进行迭代时,提取地图的
    values
    集合,使用自定义比较器对其进行排序,然后 返回已排序集合的迭代器。

  • 同时使用

    LinkedHashMap
    TreeMap
    ,并并行更新两者。

  • LinkedHashMap
    TreeMap
    创建自定义外观类。当您调用
    put
    remove
    等时,这需要使两个数据结构保持最新,并且还提供额外的方法来获取排序值。


0
投票

如果您可以通过 value 属性预先对项目进行排序,那么您可以使用

LinkedListHashMap
,因为这会保留您指定的顺序。然而,这似乎有点脆弱,如果您稍后需要向地图添加更多项目,则不适合。

另一种方法是将值存储在列表中,根据需要进行排序,然后使用二分搜索来检索项目并查找新项目的插入点。

您甚至可以将所有这些包装起来并将其放在

Map
界面后面。

Collections 类提供了 binarySearch。概要如下:

  • 将您的 Value 类放入列表中,
    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,它将是可序列化的。


0
投票

您可以对地图的entrySet进行排序并将其作为流进行处理。它不会按照添加的顺序返回值,但它允许您控制顺序,这可能比依赖地图更安全

map
  .entrySet()
  .stream()
  .sorted(Entry.comparingByValue(ValueObject::getAttribute))
  .forEach(entry -> doSomething(entry));
© www.soinside.com 2019 - 2024. All rights reserved.