清理Java8中的数据列表


11

为了清理数据列表,我创建了一种方法,该方法接受数据列表和要执行的清理操作列表。

public <T> List<T> cleanData(List<T> data, List<Function<T, T>> cleanOps) {
    List<T>dataNew=data.stream().map((str) -> {
        T cleanData = str;
        for(Function<T,T> function:cleanOps) {
            cleanData=function.apply(cleanData);
        }
        return cleanData;
    }).collect(Collectors.toList());
    return dataNew;
}

这里的问题是,当Collectors.toList()返回新列表时,我们将再次创建整个列表。我们可以在不使用额外空间的情况下达到相同的结果吗?

下面是调用代码:

public void processData() {
    List<Function<String, String>> cleanOps = new ArrayList<>();
    cleanOps.add(String::toLowerCase);
    cleanOps.add(str -> str.replaceAll(" ", ""));
    List<String> data = new ArrayList<>();
    data.add("John Doe");
    data.add("Jane Doe");
    System.out.println(Arrays.toString(cleanData(data, cleanOps).toArray()));
}

toList()返回a Collectornot List和no:没有“多余的空间”就不能拥有“额外的数据”
xerx593

Answers:


10

如果允许就地修改列表,则可以使用

public <T> List<T> cleanData(List<T> data, List<Function<T, T>> cleanOps) {
    cleanOps.stream().reduce(Function::andThen).ifPresent(f -> data.replaceAll(f::apply));
    return data;
}

andThen合并两个Function实例,并且如果存在至少一个函数(即cleanOps列表不为空),则使用,将合并后的组合函数应用于所有列表元素,并将结果替换为元素replaceAll

不幸的是,尽管在功能上是等效的,但仍replaceAll需要a UnaryOperator<T>而不是a Function<T,T>,因此我们必须使用adapter f::apply

由于这些函数类型是等效的,因此我们可以将列表更改为List<UnaryOperator<T>>,但是然后,我们不得不面对这样的事实,即没有专门的andThen实现UnaryOperator,因此我们需要:

public <T> List<T> cleanData(List<T> data, List<UnaryOperator<T>> cleanOps) {
    cleanOps.stream()
        .reduce((f1,f2) -> t -> f2.apply(f1.apply(t)))
        .ifPresent(data::replaceAll);
    return data;
}

呼叫者的来源变为

List<UnaryOperator<String>> cleanOps = new ArrayList<>();
cleanOps.add(String::toLowerCase);
cleanOps.add(str -> str.replaceAll(" ", ""));
List<String> data = new ArrayList<>();
data.add("John Doe");
data.add("Jane Doe");
System.out.println(cleanData(data, cleanOps));

然后。

附带说明一下,不需要像

System.out.println(Arrays.toString(cleanData(data, cleanOps).toArray()));

因为a的toString()方法List产生完全相同的输出。由于该println(Object)方法toString()隐式调用,因此您可以使用

System.out.println(cleanData(data, cleanOps));

7

看来您需要使用List.replaceAll(),用将给定运算符应用于该元素的结果替换此列表中的每个元素。

public <T> List<T> cleanString(List<T> data, List<Function<T, T>> cleanOps) {
    data.replaceAll(str -> {
        T cleanData = str;
        for (Function<T,T> function : cleanOps) {
            cleanData = function.apply(cleanData);
        }
        return cleanData;
    });
    return data;
}

我会重新命名方式,不过,因为它是通用的,所以它并不一定处理ListString秒。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.