我想检查一个值是否存在。
我的代码:
public static final Map<String, List<String>> m = new HashMap<>();
if(m.containsValue("gummi")) {...}
我的问题是该值是一个List。 如何查看列表?
答案 0 :(得分:13)
因此,我要解释这个问题,是想知道Map
的任何值是否包含目标String
。
可能有一个更合适的第三方双向多图实现。如果您将来要阅读此内容,则Java SE中可能有这种类型-请编辑此答案。
鉴于数据结构,这将需要搜索整个数据。让Map
用另一种方式映射可能更好。让我们忽略它。
流单线表达解决方案:
m.values().stream().anyMatch(list -> list.contains("gummi"))
编辑:对于Horse Voice(非流媒体版本)。
flatContains(m.values(), "gummi")
其中
public static boolean flatContains(
Iterable<? extends Collection<?>> collections,
Object value
) {
for (Collection<?> collection : collections) {
if (collection.contains(value)) {
return true;
}
}
return false;
}
通常避免使用流,从而使代码更具可读性(并且速度更快)。但是,在这种情况下,我会直奔潮流。如果涉及flatMap
,那么选择将更加接近。
答案 1 :(得分:2)
Map<String, List<String>> m = new HashMap<>();
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<String> list3 = new ArrayList<>();
m.put("1", list1);
m.put("2", list2);
System.out.println(m.containsValue(list1));
System.out.println(m.containsValue(list2));
System.out.println(m.containsValue(list3));
输出
true
true
true
说明
只要新列表为空,哈希码值始终为1 。因此list1,list2和list3的哈希码值都为1。基本上,
list1 = list2 = list3
所以即使我们检查m.containsValue(list3);它将返回 true 。但是,如果列表不为空,则每个列表将具有唯一的哈希码。因此,只要您的地图具有非空列表,我们就可以使用containsValue(listObject)来返回正确的结果。以下示例,
Map<String, List<String>> m = new HashMap<>();
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<String> list3 = new ArrayList<>();
list1.add("apple");
list1.add("orange");
list2.add("mobile");
list2.add("computer");
m.put("1", list1);
m.put("2", list2);
System.out.println(m.containsValue(list1));
System.out.println(m.containsValue(list2));
System.out.println(m.containsValue(list3));
输出:
true
true
false
其他用例:
如果我们要检查地图中的值是否为列表类型,或者我们要检查列表中的一个值是否存在,则可以如下迭代地图,
for (String key : m.keySet()) {
if (m.get(key) instanceof List) {
for (String listItem : m.get(key)) {
if ("valueWeSearchFor".equalsIgnoreCase(listItem)) {
break;
}
}
}else{
//If the value in the map is not of type list
//What to do!!
}
}
答案 2 :(得分:1)
引自List.equals
Javadoc:
换句话说,如果两个列表包含相同顺序的相同元素,则它们被定义为相等。
因此,要检查值是否存在,您可以创建一个列表并使用List
调用containsValue
,因为此方法将调用equals
来确定相等性。如果相同的元素具有相同的顺序,则会找到匹配项。
您可以使用Arrays.asList
List
if(m.containsValue(Arrays.asList("gummi"))) {...}
示例代码:
Map<String, List<String>> m = new HashMap<>();
List<String> list = new ArrayList<>();
list.add("1");
list.add("2");
m.put("key", list);
if (m.containsValue(Arrays.asList("1", "2"))) {
System.out.println("contains value");
}
答案 3 :(得分:1)
contains
的{{1}} 假设与Tom相同,这是Java 7版本(根据Horse Voice的要求):
Map<String, List<String>>
如果您的源Map不变,那么可能创建搜索缓存会更好:
// Live version
static boolean contains(Map<String, List<String>> map, String value) {
for (List<String> list : map.values()) {
if(list.contains(value)) return true;
}
return false;
}
// Cached version
private List<String> allValues = getInnerValues(map);
private List<String> getInnerValues(Map<String, List<String>> map) {
List<String> result = new ArrayList<>();
for (List<String> list : map.values()) {
result.addAll(list);
}
return result;
}
static boolean contains(String value) {
return allValues.contains(value);
}
和anyKeyForValue
我认为有些人会想要与值匹配的键:
keysForValue
缓存有点困难;我们需要反转地图:
// Live version
static String anyKeyForValue(Map<String, List<String>> map, String value) {
for (Entry<String, List<String>> entry : map.entrySet()) {
if(entry.getValue().contains(value)) return entry.getKey();
}
return null;
}
static List<String> keysForValue(Map<String, List<String>> map, String value) {
List<String> result = new ArrayList<>();
for (Entry<String, List<String>> entry : map.entrySet()) {
if(entry.getValue().contains(value)) result.add(entry.getKey());
}
return result;
}
答案 4 :(得分:0)
@Tom的答案是最好的,@ HorseVoice要求提供Java 7版本,如下所示:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* https://stackoverflow.com/questions/32925049/check-if-a-list-is-a-value-in-a-hashmap
*
* @author surender.kumar
*/
public class CheckListValueInHashMapExists {
public static final Map<String, List<String>> m = new HashMap<>();
public static void main(String[] args) {
System.out.println("Running main ...");
initM();
String gummi = "gummi";
System.out.println("Do the list contains value gummi? " + checkValueExistsJava7());
}
private static boolean checkValueExistsJava7() {
for (List<String> list : m.values()) {
if (list.contains("gummi")) {
return true;
}
}
return false;
}
private static void initM() {
List<String> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
list1.add("value1a");
list1.add("value1b");
list2.add("value2");
list2.add("gummi");
m.put("1", list1);
m.put("2", list2);
}
}
输出:
Running main ...
Do the list contains value gummi? true
答案 5 :(得分:0)
我认为Surender Kherwa的回答是合格的,但是我认为当您在集合中查找元素时,最好使用while
循环而不是for
,这是示例(对于Java 7):
String gummi = "gummi";
Map<String,List<String>> map = new HashMap<String,List<String>>() {
{
put("KEY1", new ArrayList<String>(){{
add("check");
add("if");
add("a");
add("list");
add("is");
}});
put("KEY2", new ArrayList<String>(){{
add("a");
add("gummi");
add("value");
add("in");
add("a");
}});
put("KEY3", new ArrayList<String>(){{
add("HashMap");
add("java");
add("7");
add("while");
add("loop");
add("version");
}});
}};
Iterator<Map.Entry<String, List<String>>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, List<String>> entry = iterator.next();
if (entry.getValue().contains(gummi)) {
System.out.println("Found in : " + entry.getKey());
break;
}
}
答案 6 :(得分:0)
如果该值为列表,则可以使用List的contains方法检查 列表具有必需的字符串。
public static void main(String args[]){
public static final Map<String, List<String>> m = new HashMap<>();
checkStringInMapOfLists("gummi",m);
}
以下方法迭代哈希图中的值,并检查哈希图中的任何列表是否包含所需的String
private boolean checkStringInMapOfLists(String input,Map<String, List<String>> m){
for(List<String> list : m.values()){
if(list.contains(input))
return true;
}
return false;
}
答案 7 :(得分:0)
我已经使用Java 8检查了两种情况。下面的分析是针对最坏的情况。
方案1:地图包含1000000个键
似乎在这种情况下,java流API比循环慢。该地图包含1000000个键。 Streams花了107543400纳秒完成任务。循环耗时73688600纳秒。但是,并行流仅花费了51464500纳秒。
签出以下解决方案代码。
public static void main(String[] args) {
try {
App app = new App();
String parameter = "invalid value";
int numberOfKeys = 1000000;
Map<String, List<String>> m = new HashMap<>();
// adding values to map
for (int i = 0; i < numberOfKeys ; i++) {
m.put(i + "",
Arrays.asList(i * 10 + "", i * 11 + "", i * 12 + "", i * 13 + "", i * 14 + "", i * 15 + ""));
}
/** check time difference **/
System.out.println("Loops");
long begin = System.nanoTime();
boolean b = app.containsValue_loops(m, parameter);
System.out.println(System.nanoTime() - begin);
System.out.println(b);
System.out.println("\nJava 8 - stream");
begin = System.nanoTime();
boolean a = app.containsValue_java8(m, parameter);
System.out.println(System.nanoTime() - begin);
System.out.println(a);
System.out.println("\nJava 8 - parallel stream");
begin = System.nanoTime();
boolean c = app.containsValue_java8_parallel(m, parameter);
System.out.println(System.nanoTime() - begin);
System.out.println(c);
} catch (Exception e) {
System.out.println(e);
}
}
/** Checks parameter contains in the list using loops **/
public boolean containsValue_loops(Map<String, List<String>> m, String parameter) {
for (List<String> list : m.values()) {
if (list.contains(parameter)) {
// return immediately if value contains in the list
return true;
}
}
return false;
}
/** Checks parameter contains in the list using streams **/
public boolean containsValue_java8(Map<String, List<String>> m, String parameter) {
return m.values().stream().anyMatch(list -> list.contains(parameter));
}
/** Checks parameter contains in the list using parallel streams **/
public boolean containsValue_java8_parallel(Map<String, List<String>> m, String parameter) {
return m.values().parallelStream().anyMatch(list -> list.contains(parameter));
}
这是输出:
Loops
73688600
false
Java 8 - stream
107543400
false
Java 8 - parallel stream
51464500
false
方案2:地图仅包含10个键
这是输出:
Loops
185000
false
Java 8 - stream
31721800
false
Java 8 - parallel stream
2987000
false
在这种情况下,for循环花费的时间少于流。它也比并行流更快。
因此,结论是我的建议是对较小的集合使用循环,如果有较大的集合,则使用并行流。
答案 8 :(得分:0)
迭代Map集合以检查每个映射值的inputString,以便您可以使用找到的匹配键来进一步使用。
Map<String, List<String>> m = new HashMap<>();
String searchStr="a";
List<String> list1 = new ArrayList<>();
list1.add("a");
list1.add("b");
m.put("1", list1);
list1 = new ArrayList<>();
list1.add("c");
m.put("2", list1);
list1 = new ArrayList<>();
list1.add("a");
list1.add("d");
m.put("3", list1);
for (Entry<String, List<String>> entry : m.entrySet()) {
if (entry.getValue().contains(searchStr)) {
System.out.println(searchStr+" found for map key="+entry.getKey());
}
}
答案 9 :(得分:0)
您必须问自己要浪费多少资源,以及该任务可以允许的运行时间是多少。因此,假设您需要一个简单的解决方案,那么该解决方案将变得非常简单。由于您使用的是哈希映射,因此键不会按任何顺序排序,因此您可以仅迭代键并查看列表是否包含值true,如果存在则中断循环。由于此解决方案过于简单,听起来像是一项家庭作业,因此我将把解决方案留给您。只是几行代码。从我的头顶看起来像:
for(String key:m.keyset()){
if(m.get(key).contains("gummi")) return true;
}
return false;
此外,如果键和列表上下文之间存在任何联系,则有许多找到解决方案的方法。一个正在使用人工智能以及回归/培训,因此您无需看列表就可以猜测列表的内容。
另一种解决方案是针对多核和并行处理的map-reduce。
看,您的问题太棒了,不同背景的不同人对问题的回答也不同。问题是,您尚未定义参数,例如所需的性能,要处理的数据量等,因此任何可行的方法都是正确的答案。
此外,在指针领域,您可以设计自己的数据结构来以最佳性能解决此问题。否则,您可以使用树木和其他杂技……但是您必须描述问题的框架。
https://plato.stanford.edu/entries/frame-problem/
在简单地将对象读取为字节数组的同时,您也可以拥有o(n)。
答案 10 :(得分:0)
这将获取映射列表中包含的任何值的键。 Java 7
public String getKeyForValue(String value) {
for (String key : map.keySet())
if (map.get(key).contains(value))
return key;
return null;
}
如果值包含在哈希映射Java 7列表内的任何位置,则返回true或false。
public boolean mapContains(String value) {
for (String key : map.keySet())
if (map.get(key).contains(value))
return true;
return false;
}
答案 11 :(得分:0)
这就是我所做的,只是将对象类型更改为您需要的任何类型
private static boolean isInListOfHash(Map<List<String>, ICommand> hashMap, String word) {
for (List<String> list : hashMap.keySet()) {
for (String string : list)
if (string.equalsIgnoreCase(word))
return true;
}
return false;
}
答案 12 :(得分:-1)
hashMap是键值存储,当您想将值搜索为值时速度很慢,因此首先将您的地图标准化,例如将其交换为键和值
Map<String, String> searchMap = m.entrySet().stream()
.flatMap(entry -> entry.getValue().stream().map(etn -> new AbstractMap.SimpleEntry<>(etn, entry.getKey())))
.collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));
和类似这样的搜索值
String mkey = searchMap.get("gummi");
现在mkey是原始地图键。 if null在原始地图中的任何值中都不存在,并且如果key不为null,您可以像这样访问创建列表
List<String> mValue = m.get(mkey);
答案 13 :(得分:-1)
如果要检查Map
的任何值内是否存在对象。使用Java-8及更高版本中涉及Stream
的方法,您可以使用flatMap
并收集toSet
在扁平化集合上执行高效contains
的情况:
boolean presentInAnyValue = m.values().stream()
.flatMap(Collection::stream)
.collect(Collectors.toSet())
.contains("gummi");
此代码的Java-7转换如下:
Set<String> set = new HashSet<>();
for (List<String> strings : m.values()) {
set.addAll(strings);
}
boolean presentInAnyValue = set.contains("gummi");