Uso di lambda per simulare i generatori Python in java

1

Attualmente mi occupo di un'app con diverse classi che vengono utilizzate per confrontare i file in vari formati (xls, csv, xml, html, pdf ...). Stanno tutti implementando un'interfaccia definita in questo modo:

public interface ReportComparator {
    // compare files (1 - match, 0 - no match, -1 - both files empty)    
    int compareTwoFiles(InputStream fileA, InputStream fileB) throws IOException;
    // gets a list of format-specific differences between two files
    List<String> getDifferences(InputStream fileA, InputStream fileB) throws IOException;
}

I comparatori specifici vengono istanziati attraverso una classe Report e successivamente utilizzati da un'applicazione GUI, che stampa i risultati del confronto. Relazione:

public class Report {
    private final String name, format;
    private final ReportComparator comparator;

    public Report(String name, String format) {
        // produce comparator specific for the format
    }
    ReportComparator getComparator() {
        return this.comparator;
    }
}

Il problema è che quando mi occupo di file di grandi dimensioni esaurisco rapidamente la memoria quando chiamo getDifferences() (l'aumento della memoria non è attualmente un'opzione). Pertanto, ho pensato di utilizzare qualcosa come un python generator , ma ho problemi a visualizzarlo in java. Dal momento che lambdas consente l'esecuzione differita, sarebbe un candidato per questo, ma sarebbe possibile mantenere questa API o almeno non dover refactoring un sacco di codice (praticamente di nuovo da zero)?

    
posta DCzo 07.09.2017 - 10:35
fonte

1 risposta

2

Non sono sicuro che si tratti di Java idiomatico, dal momento che non sono realmente un programmatore Java, ma un buon modo per farlo consiste nel riscrivere il tuo comparatore come una macchina a stati, mantenendo lo stato in qualche oggetto. Ad esempio:

public interface Coroutine {
    List<String> getPrevDiffs(void);
    String getDiff(void);
}
private class SomeSpecificReportComparison implements Coroutine {
    private InputStream a, b;
    private List<String> prevDiffs = new List<>;
    private int state = 0;
    SomeSpecificReportComparison(InputStream a, InputStream b) {
        this.a = a;
        this.b = b;
    }
    List<String> getPrevDiffs(void) {
        return prevDiffs;
    }
    String getDiff(void) {
        // diff generation goes here
        // add diff to prevDiffs
        return diff;
    }
}

La variabile state serve per memorizzare lo stato in cui è contenuta la macchina di stato getDiff e tutte le altre variabili che devono essere conservate devono essere anche variabili di istanza. Quindi, la funzione di confronto restituirà solo un'istanza di questa classe.

Per maggiori dettagli, vedi l'articolo di Simon Tatham sulle coroutine in c, che usa una tecnica simile.

    
risposta data 13.09.2017 - 01:21
fonte

Leggi altre domande sui tag