检查地图值是否包含特定字符串和限制列表中的元素

发布于 2025-01-26 22:53:20 字数 956 浏览 3 评论 0原文

我有一些这样的值的地图:

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” a“ 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以及一些从限制性列表中进行值,

但我想如何

filter()anymatch()之前尝试过它。

I have a map of some values like this:

Map<String, String> roleMap = new HashMap<>();
map.put(1,"A");
map.put(2,"B;C;D");
map.put(3,"A;C");

And the list of some restricted values:

List<String> restrictedList= List.of("B", "C");

I need to check if the value "A" is presented in each key of the map and not together with one of the values from restricted list, then throw some error.

I succeeded to do this but think it can be done better with streams fully and not a half job.

This is my solution:

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))
    };
});

The result of above scenario should output that key number 3 is invalid because only key number 3 contains "A and also some value from restricted list.

But I wonder how to implement it with streams?

I tried with filter() before anyMatch() but it doesn't work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半仙 2025-02-02 22:53:20

您可以在地图的值上创建流,并在其上应用filter()操作两次:

  • 找出代码中的目标字符串(“ a” a“ a“ a“ a“ a“ a“ a“ a“ a” a”)包含在地图值中;
  • 确定特定地图值与给定限制列表之间是否存在相交。

两项检查都是AnyMatch()操作的制作。

为了提高对受限制列表的检查的性能,它是用HashSet包裹的。

正在通过split()从每个值中创建一个字符串数组,以减少开销。

目标值(<代码>“ a” ),错误消息和定界符(“;”)被动态地传递给该方法,而不是硬编码。

该代码可能看起来像这样:

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() - emo

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]

You can create a stream over the values of the map and apply filter() operation on it twice:

  • to find out if the target string ("A") in your code is contained in the map value;
  • to determine whether there's an intersection between a particular map value and the given restricted list.

Both checks are making of anyMatch() operation.

In order to improve performance of checking against the restricted lists, it's being wrapped with a HashSet.

A string array is being created via split() operation from each value only once to reduce the overheads.

Target value ("A"), error message and delimiter (";") are being passed to the method dynamically and not hard-coded.

The code might look like this:

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() - demo

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, ";"));
}

Output

[A;C  combination can't be used with  A]
眼眸里的快感 2025-02-02 22:53:20

您可以执行下面的操作来过滤根据申请的无效值的键,并将这些键收集到列表/集合:

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);

You could do something like below to filter the keys which have invalid values according to your requierments and collect those keys to 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);

If you want to avoid two filters and calling Arrays.asList twice, you could extract a predicate like below:

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);
铁憨憨 2025-02-02 22:53:20

我建议将您的状况检查到isInrestrictallist方法。

然后,您可以使用流。过滤 地图以非常简单和干净的方式:

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的输出 is 键:3 ,A; C组合不能与'a'一起使用

I recommend extracting your condition checking to isInRestrictedList method.

Then you can use stream.filter map in a very simple and clean way like this:

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);
}

The output of errorsList is key: 3, A;C combination can't be used with 'A'

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文