Làm sạch danh sách dữ liệu trong Java8


11

Để làm sạch danh sách dữ liệu, tôi đã tạo một phương thức chấp nhận danh sách dữ liệu và danh sách thao tác làm sạch sẽ được thực hiện.

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

Vấn đề ở đây là chúng tôi đang tạo lại toàn bộ danh sách khi Collectors.toList()trả về một danh sách mới. Chúng ta có thể đạt được kết quả tương tự mà không cần sử dụng thêm không gian?

Dưới đây là mã cho lời mời:

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()trả về Collectorkhông phải là a Listvà không: bạn không thể có "dữ liệu bổ sung" mà không có "không gian thừa"
xerx593

Câu trả lời:


10

Nếu sửa đổi danh sách tại chỗ được cho phép, bạn có thể sử dụng

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

andThenkết hợp hai Functiontrường hợp và nếu có ít nhất một hàm, tức là cleanOpsdanh sách không trống, hàm kết hợp kết quả sẽ được áp dụng cho tất cả các phần tử danh sách và các phần tử được thay thế bằng kết quả, sử dụng replaceAll.

Thật không may, replaceAllđòi hỏi một UnaryOperator<T>thay vì một Function<T,T>, mặc dù tương đương về chức năng, vì vậy chúng tôi phải sử dụng bộ chuyển đổi f::apply.

Vì các loại hàm này là tương đương, chúng tôi có thể thay đổi danh sách thành List<UnaryOperator<T>>, nhưng sau đó, chúng tôi phải đối mặt với thực tế là không có andThentriển khai chuyên biệt nào UnaryOperator, vì vậy chúng tôi sẽ cần:

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

Nguồn của người gọi thay đổi thành

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

sau đó.

Là một lưu ý phụ, không cần xây dựng như

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

như toString()phương pháp của một Listsản xuất chính xác cùng một đầu ra. Vì println(Object)phương thức gọi toString()ngầm, bạn chỉ có thể sử dụng

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

7

Có vẻ như bạn cần sử dụng List.replaceAll(), thay thế từng phần tử của danh sách này bằng kết quả của việc áp dụng toán tử đã cho cho phần tử đó.

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

Tôi muốn đổi tên phương pháp, tuy nhiên, vì nó chung chung, vì vậy nó không nhất thiết phải xử lý một Listcủa Strings.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.