簡體   English   中英

如何使用Java 8流過濾具有兩個列表的對象?

[英]How to filter objects with two lists using java 8 stream?

我需要過濾包含大量對象的列表。 對於這些對象中的每一個,我需要驗證是否有任何參數包含其他列表中的單詞之一。 我已經開發出一種方法來執行此操作,但是花費的時間太長了,我想知道是否有一種更有效的方法來執行此操作。

主要思想可以用sql編寫以便更好地理解:

SELECT * FROM PROJECT P WHERE P.NAME LIKE "%JAVA%" OR P.NAME LIKE "%PASCAL%" OR P.PRODUCT LIKE "%JAVA%" OR P.PRODUCT LIKE "%PASCAL% OR. P.ADDRESS LIKE "%JAVA" OR P.ADDRESS LIKE "%PASCAL%";

在Java中,我是這樣寫的:

private List<Projeto> filtraResultado(List<Projeto> projetosAssinados, String[] filtros){
List<Projeto> result = new ArrayList<Projeto>();
for(Projeto p: projetosAssinados) {
    if(existeFiltroBuscadoNosCamposDePesquisa(p.getDsProjeto(), filtros) ||
       existeFiltroBuscadoNosCamposDePesquisa(p.getNomeProjeto(), filtros) ||
       existeFiltroBuscadoNosCamposDePesquisa(p.getSetor(),filtros) ||
       existeFiltroBuscadoNosCamposDePesquisa(p.getUn(), filtros) ||
       existeFiltroBuscadoNosCamposDePesquisa(p.getProcessosModelados(),filtros)||
       existeFiltroBuscadoNosCamposDePesquisa(p.getServicosPrestados(),filtros) ||
       existeFiltroBuscadoNosCamposDePesquisa(p.getTecnologias(),filtros)||
       existeFiltroBuscadoNosCamposDePesquisa(p.getDetalhamento(),filtros)) {
            result.add(p);
    }

}
return result;

}

public boolean existeFiltroBuscadoNosCamposDePesquisa(String campoPesquisado,String[] filtros ){
if(campoPesquisado == null) {
    return false;
}
for(String f: filtros) {
    if(StringUtils.containsIgnoreCase(campoPesquisado, f.trim())) {
        return true;
    }
}
return false;

}

通過創建包含過濾器元素的Set<String>可以改善方法的時間復雜度。 這樣,搜索特定元素將是O(1)而不是O(n)

private List<Projeto> filtraResultado(List<Projeto> projetosAssinados, String[] filtros) {
    Set<String> filterSet = Arrays.stream(filtros)
            .map(String::toLowerCase)
            .map(String::trim)
            .collect(Collectors.toSet());

    List<Projeto> result = new ArrayList<Projeto>();

    for (Projeto p : projetosAssinados) {
        boolean contained = Stream.of(p.getDsProjeto(), p.getNomeProjeto(),
                p.getSetor(), p.getUn(), p.getProcessosModelados(), 
                p.getServicosPrestados(), p.getTecnologias(), p.getDetalhamento())
            .filter(Objects::nonNull)
            .map(String::toLowerCase)
            .anyMatch(filterSet::contains);

        if (contained) {
            result.add(p);
        }
    }

    return result;
}

對於大型輸入,這應該比您的方法快得多。

為了比較兩個List您需要anyMatch()並在兩個列表之間進行流傳輸。 但是,如果您要檢查filter我認為該列表上的每個記錄都是不同的,並且可以輕松地將其轉換為使用Set ,這將減少時間並提高速度。

例如:

List< String > filterList = Arrays.asList( "z" );
List< String > toCheckList = Arrays.asList( "z", "b", "a", "q", "w" );

boolean contains = toCheckList.stream( ).anyMatch( list -> filterList.stream( ).anyMatch( filter -> StringUtils.containsIgnoreCase( filter, list ) ) );

    if ( contains ) {
        System.out.println( "Contains" );
        //your logic
    }

如果您的過濾器是Set

Set< String > filterList = Arrays.asList( "z", "b" ).stream( ).collect( Collectors.toSet( ) );
List< String > toCheckList = Arrays.asList( "z", "b", "a", "q", "w" );
boolean contains = toCheckList.stream( ).anyMatch( list -> filterList.contains( list ) );

    if ( contains ) {
        System.out.println( "Contains" );

        //your logic
    }

請考慮一下是否可以將代碼上的過濾器List更改為“ Set ”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM