Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Logging 使用流API记录排除结果的更好方法_Logging_Java 8_Java Stream - Fatal编程技术网

Logging 使用流API记录排除结果的更好方法

Logging 使用流API记录排除结果的更好方法,logging,java-8,java-stream,Logging,Java 8,Java Stream,我想知道有没有办法重写这样的代码 public static void main(String[] args) { final List<String> dataCollection = Collections.emptyList(); final Set<String> someValues = new HashSet<>(); final Iterator<String> iterator = dataCollectio

我想知道有没有办法重写这样的代码

public static void main(String[] args) {
    final List<String> dataCollection = Collections.emptyList();
    final Set<String> someValues = new HashSet<>();
    final Iterator<String> iterator = dataCollection.iterator();
    while (iterator.hasNext()) {
        final String dataItem = iterator.next();
        // imagine some calculations
        String calculatedData = dataItem;
        if (!someValues.contains(calculatedData)) {
            logger.error("Skipped data {} because of ...#1", dataItem);
            iterator.remove();
            continue;
        }

        for (char element : dataItem.toCharArray()) {
            // imagine some other calculations
            if (element > 100) {
                logger.error("Skipped data {} because of ...#2", dataItem);
                iterator.remove();
                break;
            }
        }
    }
}

我希望有更好的方法。

假设跳绳是一种特殊情况,这可能是可行的

List<String> dataCollection = Arrays.asList("FOO", "hello", "VALID", "123", "BAR", "bla");
Set<String> someValues = new HashSet<>(Arrays.asList("FOO", "BAR"));

Predicate<String> firstPredicate  = string -> !someValues.contains(string);
Predicate<String> secondPredicate = string -> string.chars().noneMatch(c -> c>100);

List<String> result;

if(!logger.isLoggable(Level.WARNING)) {
    result = dataCollection.stream()
           .filter(firstPredicate)
           .filter(secondPredicate)
           .collect(Collectors.toList());
}
else {
    Map<Boolean, List<String>> map = dataCollection.stream()
        .collect(Collectors.partitioningBy(firstPredicate));
    if(!map.get(false).isEmpty())
        logger.log(Level.WARNING, "Skipped data {0} because of ...#1", map.get(false));
    map = map.get(true).stream()
        .collect(Collectors.partitioningBy(secondPredicate));
    if(!map.get(false).isEmpty())
        logger.log(Level.WARNING, "Skipped data {0} because of ...#2", map.get(false));
    result = map.get(true);
}

结果是,
[VALID,123]
,无论是否启用该级别的日志记录。

首先,我认为OP中的代码还不错。其次,我们仍然可以通过原始代码做一些改进:

final Predicate<String> loggingFilter = dataItem -> {
    final String calculatedData = dataItem; // imagine some calculations
    if (!someValues.contains(calculatedData)) {
        logger.error("Skipped data {} because of ...#1", dataItem);
        return false;
    }         
    final OptionalInt element = dataItem.chars().filter(ch -> ch > 100).findAny();
    if (element.isPresent()) {
        logger.error("Skipped data {} because of element {}...#2", dataItem, element.getAsInt());
        return false;
    }
    return true;
};

dataCollection.stream().filter(loggingFilter).collect(Collectors.toList());
final Predicate loggingFilter=dataItem->{
最后一个字符串calculatedData=dataItem;//想象一些计算
如果(!someValues.contains(calculatedData)){
错误(“跳过数据{},因为…#1”,数据项);
返回false;
}         
final optionant元素=dataItem.chars().filter(ch->ch>100.findAny();
if(element.isPresent()){
错误(“由于元素{}…#2”,dataItem,element.getAsInt())跳过了数据{});
返回false;
}
返回true;
};
dataCollection.stream().filter(loggingFilter.collect(Collectors.toList());

我不确定这对你或其他人来说是不是“冗长、笨拙和类似副作用”。对我来说,没有重复的代码或副作用。这几乎是任何语言都能做到的,除了一些语言可能提供链式操作API来删除
if(…);如果(…)

可能是
谓词
的扩展?像
接口LoggingPredicate扩展谓词…
和静态方法
静态LoggingPredicate(Logger log)
一样,它将创建它并覆盖
测试方法。只是个主意…是的,但是。。。这是包装此代码的另一种方式。当然,它比Mine具有更好的可重用性。我认为没有其他方法可以做到这一点,因为Stream API除了
peek
之外没有任何日志记录功能。跳过项和调用
iterator.remove()
之间有根本区别。一般来说,streams不支持这种修改。是的,我知道。对于这个问题,修改现有集合或创建新集合并不重要。请专注于日志记录关于将流拆分为两个的好主意。它是处理数据流的一种被动方式。不幸的是,在(至少在java中)这种拆分是终端操作,它破坏了流延迟评估的潜力。现在还有两个代码块计算结果,实际上是业务算法的重复
final Predicate<String> loggingFilter = dataItem -> {
    final String calculatedData = dataItem; // imagine some calculations
    if (!someValues.contains(calculatedData)) {
        logger.error("Skipped data {} because of ...#1", dataItem);
        return false;
    }         
    final OptionalInt element = dataItem.chars().filter(ch -> ch > 100).findAny();
    if (element.isPresent()) {
        logger.error("Skipped data {} because of element {}...#2", dataItem, element.getAsInt());
        return false;
    }
    return true;
};

dataCollection.stream().filter(loggingFilter).collect(Collectors.toList());