检查映射值是否包含特定字符串和受限列表中的元素
Check if a Map Value contains a particular String and an element from the restricted List
我有这样一些值的映射:
Map<String, String> roleMap = new HashMap<>();
map.put(1,"A");
map.put(2,"B;C;D");
map.put(3,"A;C");
以及一些限制值的列表:
List<String> restrictedList= List.of("B", "C");
我需要检查值 "A"
是否出现在地图的每个键中,而不是与受限列表中的值之一一起出现,然后抛出一些错误。
我成功做到了这一点,但我认为完全使用流可以做得更好,而不是半途而废。
这是我的解决方案:
map.forEach((key, value) -> {
if (Arrays.stream(value.toString().split(";"))
.anyMatch(role -> "A".contains(role))
&& CollectionUtils.containsAny(Arrays.asList(value.toString().split(";")), restrictedList)) {
errorsList.add(String.format("%s combination can't be used with 'A'", value))
};
});
上述场景的结果应该输出密钥编号 3
无效,因为只有密钥编号 3
包含 "A
以及限制列表中的一些值。
但是我想知道如何用流来实现它?
我在 anyMatch()
之前尝试过 filter()
,但它不起作用。
我建议将您的条件检查提取到 isInRestrictedList
方法。
然后你可以使用流。filter
map
以一种非常简单干净的方式,如下所示:
List<String> errorsList = map.entrySet()
.stream()
.filter(entry -> isInRestrictedList(entry.getValue()))
.map(entry -> String.format("key: %s, %s combination can't be used with 'A'", entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
private boolean isInRestrictedList(String value) {
List<String> restrictedList = Arrays.asList("B", "C");
List<String> source = Arrays.asList(value.split(";"));
return source.contains("A") && CollectionUtils.containsAny(source, restrictedList);
}
errorsList
的输出是key: 3, A;C combination can't be used with 'A'
您可以在地图的值上创建一个流并对其应用 filter()
操作两次:
- 找出你代码中的目标字符串(
"A"
)是否包含在映射值中;
- 确定特定映射值与给定限制列表之间是否存在交集。
两项检查都在进行 anyMatch()
操作。
为了提高检查受限列表的性能,它用 HashSet
包装起来。
正在通过 split()
从每个值仅执行一次操作创建字符串数组以减少开销。
目标值 ("A"
)、错误消息和分隔符 (";"
) 正在动态传递给方法,而不是 hard-coded。
代码可能如下所示:
public static List<String> getErrorList(List<String> restricted,
Map<String, String> map,
String targetValue, // in your code "A"
String errorMessage,
String delimiter) {
Set<String> restrictedSet = new HashSet<>(restricted); // list is being wrapped by the set to improve performance
return map.values().stream() // Stream<String>
.map(str -> str.split(delimiter)) // Stream<String[]>
.filter(arr -> Arrays.stream(arr).anyMatch(targetValue::equals)) // contain the target value
.filter(arr -> Arrays.stream(arr).anyMatch(restrictedSet::contains)) // contains any of the restricted values
.map(arr -> String.join(delimiter, arr)) // Stream<String>
.map(str -> String.format("%s %s %s", str, errorMessage, targetValue))
.collect(Collectors.toList());
}
main()
- 演示
public static void main(String[] args) {
Map<String, String> roleMap =
Map.of("1","A", "2","B;C;D", "3","A;C");
List<String> restrictedValues = List.of("B", "C");
String errorMessage = " combination can't be used with ";
String targetValue = "A";
System.out.println(getErrorList(restrictedValues, roleMap, targetValue, errorMessage, ";"));
}
输出
[A;C combination can't be used with A]
您可以执行如下操作,根据您的要求过滤具有无效值的键,并将这些键收集到 list/set:
Map<Integer,String> map = new HashMap<>();
map.put(1,"A");
map.put(2,"B;C;D");
map.put(3,"A;C");
List<String> restrictedList= List.of("B", "C");
List<Integer> invalidKeys = map.entrySet().stream()
.filter(e -> Arrays.asList(e.getValue().split(";")).contains("A"))
.filter(e -> Arrays.asList(e.getValue().split(";")).stream().anyMatch(restrictedList::contains))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(invalidKeys);
如果您想避免使用两个过滤器并调用 Arrays.asList
两次,您可以提取如下谓词:
Predicate<String> containsRestrictedValueAndA = s -> {
List<String> temp = Arrays.asList(s.split(";"));
return temp.contains("A") && temp.stream().anyMatch(restrictedList::contains);
};
List<Integer> invalidKeys2 = map.entrySet().stream()
.filter( e -> containsRestrictedValueAndA.test(e.getValue()))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(invalidKeys2);
我有这样一些值的映射:
Map<String, String> roleMap = new HashMap<>();
map.put(1,"A");
map.put(2,"B;C;D");
map.put(3,"A;C");
以及一些限制值的列表:
List<String> restrictedList= List.of("B", "C");
我需要检查值 "A"
是否出现在地图的每个键中,而不是与受限列表中的值之一一起出现,然后抛出一些错误。
我成功做到了这一点,但我认为完全使用流可以做得更好,而不是半途而废。
这是我的解决方案:
map.forEach((key, value) -> {
if (Arrays.stream(value.toString().split(";"))
.anyMatch(role -> "A".contains(role))
&& CollectionUtils.containsAny(Arrays.asList(value.toString().split(";")), restrictedList)) {
errorsList.add(String.format("%s combination can't be used with 'A'", value))
};
});
上述场景的结果应该输出密钥编号 3
无效,因为只有密钥编号 3
包含 "A
以及限制列表中的一些值。
但是我想知道如何用流来实现它?
我在 anyMatch()
之前尝试过 filter()
,但它不起作用。
我建议将您的条件检查提取到 isInRestrictedList
方法。
然后你可以使用流。filter
map
以一种非常简单干净的方式,如下所示:
List<String> errorsList = map.entrySet()
.stream()
.filter(entry -> isInRestrictedList(entry.getValue()))
.map(entry -> String.format("key: %s, %s combination can't be used with 'A'", entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
private boolean isInRestrictedList(String value) {
List<String> restrictedList = Arrays.asList("B", "C");
List<String> source = Arrays.asList(value.split(";"));
return source.contains("A") && CollectionUtils.containsAny(source, restrictedList);
}
errorsList
的输出是key: 3, A;C combination can't be used with 'A'
您可以在地图的值上创建一个流并对其应用 filter()
操作两次:
- 找出你代码中的目标字符串(
"A"
)是否包含在映射值中; - 确定特定映射值与给定限制列表之间是否存在交集。
两项检查都在进行 anyMatch()
操作。
为了提高检查受限列表的性能,它用 HashSet
包装起来。
正在通过 split()
从每个值仅执行一次操作创建字符串数组以减少开销。
目标值 ("A"
)、错误消息和分隔符 (";"
) 正在动态传递给方法,而不是 hard-coded。
代码可能如下所示:
public static List<String> getErrorList(List<String> restricted,
Map<String, String> map,
String targetValue, // in your code "A"
String errorMessage,
String delimiter) {
Set<String> restrictedSet = new HashSet<>(restricted); // list is being wrapped by the set to improve performance
return map.values().stream() // Stream<String>
.map(str -> str.split(delimiter)) // Stream<String[]>
.filter(arr -> Arrays.stream(arr).anyMatch(targetValue::equals)) // contain the target value
.filter(arr -> Arrays.stream(arr).anyMatch(restrictedSet::contains)) // contains any of the restricted values
.map(arr -> String.join(delimiter, arr)) // Stream<String>
.map(str -> String.format("%s %s %s", str, errorMessage, targetValue))
.collect(Collectors.toList());
}
main()
- 演示
public static void main(String[] args) {
Map<String, String> roleMap =
Map.of("1","A", "2","B;C;D", "3","A;C");
List<String> restrictedValues = List.of("B", "C");
String errorMessage = " combination can't be used with ";
String targetValue = "A";
System.out.println(getErrorList(restrictedValues, roleMap, targetValue, errorMessage, ";"));
}
输出
[A;C combination can't be used with A]
您可以执行如下操作,根据您的要求过滤具有无效值的键,并将这些键收集到 list/set:
Map<Integer,String> map = new HashMap<>();
map.put(1,"A");
map.put(2,"B;C;D");
map.put(3,"A;C");
List<String> restrictedList= List.of("B", "C");
List<Integer> invalidKeys = map.entrySet().stream()
.filter(e -> Arrays.asList(e.getValue().split(";")).contains("A"))
.filter(e -> Arrays.asList(e.getValue().split(";")).stream().anyMatch(restrictedList::contains))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(invalidKeys);
如果您想避免使用两个过滤器并调用 Arrays.asList
两次,您可以提取如下谓词:
Predicate<String> containsRestrictedValueAndA = s -> {
List<String> temp = Arrays.asList(s.split(";"));
return temp.contains("A") && temp.stream().anyMatch(restrictedList::contains);
};
List<Integer> invalidKeys2 = map.entrySet().stream()
.filter( e -> containsRestrictedValueAndA.test(e.getValue()))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(invalidKeys2);