Java8'deki veri listesini temizleme


11

Bir veri listesini temizlemek için, veri listesini ve gerçekleştirilecek temizlik işlemi listesini kabul eden bir yöntem oluşturdum.

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

Buradaki sorun, Collectors.toList()yeni bir liste döndürürken tüm listeyi yeniden oluşturmamızdır . Fazladan alanı kullanmadan aynı sonucu elde edebilir miyiz?

Çağırma kodu aşağıdadır:

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()döner bir Collectordeğil Listve hiçbir: Eğer "ekstra alan" olmadan "ekstra veri" olamaz
xerx593

Yanıtlar:


10

Listede yerinde değişiklik yapılmasına izin veriliyorsa,

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

andTheniki Functionörneği birleştirir ve en az bir işlev mevcutsa, yani cleanOpsliste boş değilse, sonuç olarak birleştirilmiş işlev tüm liste öğelerine ve sonuç tarafından değiştirilen öğelere kullanılarak uygulanır replaceAll.

Ne yazık ki, işlevsel olarak eşdeğer olmasına rağmen, replaceAlla UnaryOperator<T>yerine bir tane gerektirir Function<T,T>, bu yüzden adaptörü kullanmalıyız f::apply.

Bu işlev türleri eşdeğer olduğundan, listeyi şu şekilde değiştirebiliriz List<UnaryOperator<T>>, ancak daha sonra, özel bir andThenuygulama olmadığı gerçeğiyle yüzleşmek zorundayız UnaryOperator, bu yüzden ihtiyacımız olacak:

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

Arayanın kaynağı şu şekilde değişir:

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

sonra.

Bir yan not olarak, benzer bir yapıya gerek yoktur.

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

olarak toString()bir yöntem Listaynı çıktı üretir. Yana println(Object)yöntemini çağırır toString()örtük, sadece kullanabilirsiniz

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

7

Görünüşe göre List.replaceAll(), bu listenin her bir elemanını, verilen operatörü o öğeye uygulama sonucuyla değiştirir.

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

O jenerik olduğundan mutlaka bir işlemez yüzden olsa da, yöntem adlandırmak istiyorum Listait Strings.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.