在HashMap中搜索值

时间:2015-12-26 19:10:12

标签: java arraylist hashmap

我有一个以下类型的HashMap:HashMap<LocalDate, ArrayList<String>>包含如下值:

2015-12-26=[John, J.Fox , Barry]
2015-12-24=[Barry, Michael, Martin],
2015-12-20=[McAllister, Barry, Clark]
..............

现在,如果我想在"Barry"中搜索HashMap并获取最新的密钥(在这种情况下是12月26日),我将如何进行此操作?

.values()方法似乎不起作用,因为每个键都有一个ArrayList而不是一个元素。

3 个答案:

答案 0 :(得分:3)

在java 8中,您可以使用以下内容:

Optional<Map.Entry<LocalDate, List<String>>> first = map
            .entrySet()
            .stream()
            .filter(entry -> entry.getValue().contains("Barry"))
            .sorted(Map.Entry.comparingByKey())
            .findFirst();

这将获取地图中的所有条目,根据值过滤它们,根据键对它们进行排序并获取第一个条目(如果有)。然后,您可以使用first.ifPresent()方法对第一个条目执行任何操作,此处我只是将它们打印到控制台:

first.ifPresent(entry -> {
            System.out.println(entry);
        });

也许这是 NOT 最有效的算法,但确定无误

更新1:要对最新到最早的日期进行排序,请使用以下命令:

sorted(Map.Entry.<LocalDate, List<String>>comparingByKey().reversed())

更新2:正如安德烈亚斯所说,您可以使用max代替sorted,而Optional<Map.Entry<LocalDate, List<String>>> found = map .entrySet() .stream() .filter(entry -> entry.getValue().contains("Barry")) .max(Map.Entry.comparingByKey()); 具有更好的渐近行为。事实上,由于您只需要最新的项目,因此无需对条目进行排序以获取它:

struct Header {
   char tag[3];
   char ver;
   char rev;
   char flags;
   uint8_t hSize[4];
};

struct ContentFrame 
{
   char id[4];
   uint32_t contentSize;
   char flags[2];
};

int ID3_sync_safe_to_int(uint8_t* sync_safe)
{
   uint32_t byte0 = sync_safe[0];
   uint32_t byte1 = sync_safe[1];
   uint32_t byte2 = sync_safe[2];
   uint32_t byte3 = sync_safe[3];

   return byte0 << 21 | byte1 << 14 | byte2 << 7 | byte3;
}

const int FRAMESIZE = 10;

答案 1 :(得分:2)

使用地图的Entry Set。例如:

HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();

ArrayList<String> list1 = new ArrayList<String>();
ArrayList<String> list2 = new ArrayList<String>();

list1.add("One");
list1.add("Two");
list1.add("Three");

list2.add("Cat");
list2.add("Dog");
list2.add("Fish");

map.put("Numbers", list1);
map.put("Animals", list2);

for(Map.Entry<String, ArrayList<String>> entry : map.entrySet())
{
    if(entry.getValue().contains("Cat"))
        System.out.println("Found Cat in "+entry.getKey());
}

输出:Found Cat in Animals

基本上,我们正在做的是迭代在地图的Entry Set上,检查每个value(我们指定的是ArrayList<String>)是否包含{ {1}}我们正在寻找,如果是,我们会打印出当前String的{​​{1}}。 (在您的情况下,这将是您的key。)

答案 2 :(得分:1)

由于您希望在搜索值时找到密钥,因此需要使用entrySet()

鉴于您的密钥是日期,因此具有自然顺序,并且您想要最新的匹配日期,您有3种选择:

  • 保留HashMap,搜索整个列表,并记住最大的键值。
  • 更改为TreeMap,使用descendingMap()向后搜索,然后在第一次点击时停止。
  • 更改为逆序TreeMap,搜索并在首次点击时停止。

如果您的列表很大和/或您进行了大量搜索,出于性能原因,最好使用TreeMap

由于不清楚LocalDate是来自Java 8还是来自Joda-Time,因此以下代码使用compareTo,它由两者实现。代码不使用Java 8特定功能。

以下是3个版本:

// HashMap
HashMap<LocalDate, ArrayList<String>> map = new HashMap<>();
...
LocalDate matchedKey = null;
for (Entry<LocalDate, ArrayList<String>> entry : map.entrySet())
    if (entry.getValue().contains(valueToFind))
        if (matchedKey == null || entry.getKey().compareTo(matchedKey) > 0)
            matchedKey = entry.getKey();
// TreeMap (descending search)
TreeMap<LocalDate, ArrayList<String>> map = new TreeMap<>();
...
LocalDate matchedKey = null;
for (Entry<LocalDate, ArrayList<String>> entry : map.descendingMap().entrySet())
    if (entry.getValue().contains(valueToFind)) {
        matchedKey = entry.getKey();
        break;
    }
// TreeMap (reverse-order)
TreeMap<LocalDate, ArrayList<String>> map = new TreeMap<>(Collections.reverseOrder()); // or Comparator.reverseOrder() in Java 8
...
LocalDate matchedKey = null;
for (Entry<LocalDate, ArrayList<String>> entry : map.entrySet())
    if (entry.getValue().contains(valueToFind)) {
        matchedKey = entry.getKey();
        break;
    }

当然,在Java 8中,这些也可以使用流和Lambdas来完成。