简体   繁体   English

用于验证映射中的 int 的 Java 流

[英]Java stream to validate int in a map

I have the below code, It just checks the given number against a map that has a number ranges.我有下面的代码,它只是根据具有数字范围的地图检查给定的数字。 The method isWithinAnyRange would check if the number is in the range including the start but excluding the end.方法 isWithinAnyRange 将检查数字是否在包括开始但不包括结束的范围内。

This works fine but I wanted to simplify that method with a stream.这工作正常,但我想用流简化该方法。

public static void main(String [] args)
{
    Map<Integer,Integer> intMap = new HashMap<>();

    intMap.put(0,2);
    intMap.put(3,4);
    intMap.put(6,9);
    System.out.println(isWithinAnyRange(intMap,2)); //false
    System.out.println(isWithinAnyRange(intMap,3)); //true
    System.out.println(isWithinAnyRange(intMap,4)); //false
    System.out.println(isWithinAnyRange(intMap,6)); //true
    System.out.println(isWithinAnyRange(intMap,7)); //true
}

public static boolean isWithinAnyRange(Map<Integer,Integer> intMap, Integer num){
   for(Map.Entry<Integer,Integer> entry: intMap.entrySet()){
       if(num>=entry.getKey() && num<entry.getValue()){
           return true;
       }
   }
   return false;
}

When all your ranges are non-overlapping, like in your example, you are better off using a TreeMap :当您的所有范围都不重叠时,例如在您的示例中,您最好使用TreeMap

public static void main(String [] args) {
    TreeMap<Integer,Integer> intMap = new TreeMap<>();
    intMap.put(0,2);
    intMap.put(3,4);
    intMap.put(6,9);
    System.out.println(isWithinAnyRange(intMap,2)); //false
    System.out.println(isWithinAnyRange(intMap,3)); //true
    System.out.println(isWithinAnyRange(intMap,4)); //false
    System.out.println(isWithinAnyRange(intMap,6)); //true
    System.out.println(isWithinAnyRange(intMap,7)); //true
}

public static boolean isWithinAnyRange(NavigableMap<Integer,Integer> intMap, Integer num) {
    Map.Entry<Integer,Integer> e = intMap.floorEntry(num);
    return e != null && num < e.getValue();
}

This is not only simpler, it is more efficient than a linear search.这不仅更简单,而且比线性搜索更有效。 More formally, the time complexity is O(log n) rather than O(n).更正式地说,时间复杂度是 O(log n) 而不是 O(n)。

Another option for small to medium sized ranges is a BitSet :中小型范围的另一个选择是BitSet

BitSet bitSet = new BitSet();
bitSet.set(0,2);
bitSet.set(3,4);
bitSet.set(6,9);
System.out.println(bitSet.get(2)); //false
System.out.println(bitSet.get(3)); //true
System.out.println(bitSet.get(4)); //false
System.out.println(bitSet.get(6)); //true
System.out.println(bitSet.get(7)); //true

This even has O(1) time complexity.这甚至具有 O(1) 时间复杂度。 It stores for all values between zero and the largest number whether they are contained or not, but it only uses one bit per number, eg for this example where all values are in within a 0 .. 64 range, a single long value will be used behind the scenes.它存储零和最大数字之间的所有值,无论它们是否包含,但每个数字仅使用一位,例如,对于所有值都在0 .. 64范围内的示例,单个long值将是在幕后使用。 But it's not suitable when you have very large ranges or distances.但是当您有非常大的范围或距离时,它不适合。 Also, when the distances are small but there are negative values or all values far away from zero, an offset would be needed to adjust the values stored in the bitset.此外,当距离很小但存在负值或所有值远离零时,将需要一个偏移量来调整存储在位集中的值。

If you just want to know if an entry matches:如果您只想知道条目是否匹配:

boolean isMatch = 
    intMap.entrySet().stream()
        .anyMatch(e -> num >= e.getKey() && num < e.getValue());

If you want to find the matching entry:如果要查找匹配的条目:

Optional<Map.Entry<Integer, Integer>> match =
    intMap.entrySet().stream()
        .filter(e -> num >= e.getKey() && num < e.getValue())
        .findAny();

If there could be multiple matching entries you can collect them back into a map:如果可能有多个匹配的条目,您可以将它们收集回地图:

Map<Integer, Integer> matches =
    intMap.entrySet().stream()
        .filter(e -> num >= e.getKey() && num < e.getValue())
        .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM