加入过滤后的地图值

时间:2018-04-03 14:59:32

标签: java java-8

我有一个静态地图如下:

private static final Map<String, String> queries;
static {
    Map<String, String> tmpMap = new HashMap<>();
    tmpMap.put("USER_WITHOUT_ROLE_QUERY","...");
    tmpMap.put("PROFIL_WITHOUT_ROLE_QUERY","...");
    //Removed code for readability 
    queries = Collections.unmodifiableMap(tmpMap);
}

以下两个String数组:

  • String[] typeFilter可以包含以下值的组合: [&#34; WITHOUT_PROFIL&#34;,&#34; WITHOUT_ROLE&#34;,&#34; WITHOUT_USER&#34;];
  • String[] elementFilter可以包含以下值的组合:[&#34; PROFIL&#34;, &#34;角色&#34;,&#34; UTILISATEUR&#34;];

我想要做的是取决于typeFilterelementFilter中的值来过滤queries地图,并使用" UNION "加入过滤后的地图的值。< / p>

例如,如果typeFilter包含"WITHOUT_ROLE"elementFilter包含"PROFIL""USER",则过滤后的地图将只包含PROFIL_WITHOUT_ROLE_QUERY和{{1}因此,结果将是:USER_WITHOUT_ROLE_QUERY

这就是我的尝试:

queries.get("PROFIL_WITHOUT_ROLE_QUERY") + " UNION " + queries.get("USER_WITHOUT_ROLE_QUERY")

我该如何解决这个问题?是否有更好的方法来执行上述代码?

5 个答案:

答案 0 :(得分:0)

您可以尝试以下操作。

List<String> queriesToJoin = queries.entrySet().stream().filter(e -> queriesMapKeys.contains(e.getKey())).collect(Collectors.toList());

String sqlQuery = String.join(" UNION ", queriesToJoin);

答案 1 :(得分:0)

您不必使用流。您可以使用StringJoiner类:

import java.util.StringJoiner;

<...>
StringJoiner builder = new StringJoiner(" UNION ");
for (String element : elementFilter) {
  for (String type : typeFilter) {
    String key = element + "_" + type + "_QUERY";
    if (queries.containsKey(key)) {
      builder.add(queries.get(key));
    }
  }
}

String sqlQuery = builder.toString();

琐事:StringJoiner类是您在执行String::join时从内部使用的内容,或使用StreamCollectors.joining收集的内容。

答案 2 :(得分:0)

您似乎只想从地图中获取一组键的值。这将是一条直线:

 List<String> queriesToJoin = queries
     .entrySet()
     .stream()
     .filter(e -> queriesMapKeys.contains(e.getKey()))
     .map(Map.Entry::getValue)
     .collect(Collectors.toList());

您还需要一种更好的方法来实现它。

使用格式化字符串为查询和过滤器的某些属性建模。您可以尝试的是使用类或谓词来执行此操作。

例如,不要使用字符串作为查询的键/名称,而应考虑使用枚举。

 public enum QueryId {
     USER_WITHOUT_ROLE_QUERY(USER, WITHOUT_ROLE),
     PROFIL_WITHOUT_ROLE_QUERY(PROFIL, WITHOUT_ROLE);
     QueryId(TargetElement element, QueryType type) {...}
     public TargetElement getElement() {...}
     public QueryType getQueryType() {...}
 }

然后,您可以使用QueryId.getElement()QueryId.getQueryType()

的谓词进行过滤

答案 3 :(得分:0)

如果要将第一个嵌套循环与过滤地图的代码合并

,请尝试使用此方法
String[] queriesToJoin =  Arrays.asList(elementFilter)
        .stream()
        .flatMap(f -> Arrays.asList(typeFilter)
                .stream()
                .map(s -> f + "_" + s + "_QUERY"))
        .filter(t -> queries.containsKey(t))
        .map(t -> queries.get(t))
        .collect(Collectors.toList()).toArray(new String [0]);

答案 4 :(得分:0)

在您的代码中

// Filter queries map
List<String> queriesMapKeys = new ArrayList<>();
for (String element : elementFilter) {
    for (String type : typeFilter) {
        queriesMapKeys.add(queries.get(element + "_" + type + "_QUERY"));
    }
}

您已经在查询地图并将get的结果添加到queriesMapKeys列表中。如果某个键不在地图中,则null引用将显示在列表中。密钥在该列表中不可用。因此,执行另一个流操作尝试将列表与地图键匹配,如

String[] queriesToJoin = queries.entrySet().stream()
    .filter(e -> queriesMapKeys.contains(e.getKey())) …

根本无法运作。

但无论如何都没有必要。您只需处理潜在的null值。之一:

queriesMapKeys.removeIf(Objects::isNull);
String sqlQuery = String.join(" UNION ", queriesMapKeys);

String sqlQuery = queriesMapKeys.stream()
    .filter(Objects::nonNull)
    .collect(Collectors.joining(" UNION "));

后者可以与前面的流操作合并,替换创建queriesMapKeys的嵌套循环:

String sqlQuery = Arrays.stream(elementFilter)
    .flatMap(element -> Arrays.stream(typeFilter)
        .map(type -> queries.get(element + "_" + type + "_QUERY")))                
    .filter(Objects::nonNull)
    .collect(Collectors.joining(" UNION "));