我需要过滤包含大量对象的列表。对于这些对象中的每一个,我需要验证是否有任何参数包含其他列表中的单词之一。我已经开发出一种方法来执行此操作,但是它花费的时间太长了,我想知道是否有一种更有效的方法可以做到这一点。
主要思想可以用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;
}
答案 0 :(得分:4)
可以通过创建包含过滤器元素的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;
}
对于大型输入,这应该比您的方法快得多。
答案 1 :(得分:3)
要比较两个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
。