在Java 8中将属性过滤/排序到地图中

时间:2017-11-26 11:35:26

标签: java lambda java-8 java-stream

我正在尝试在运行时读取Java系统属性,基于includes列表(此处硬编码但通常通过属性文件注入)进行过滤,最后按键排序,转换为Map<String, String>。这就是我提出的,但不确定它是否是最优雅的解决方案。

final List<String> includes = Arrays
    .asList("java.version", "PID", "os.name", "user.country");     // hard coded here but (usually defined in a properties file)

Map<String, String> systemMap = System.getProperties()
    .entrySet().stream()
    .filter(s -> includes != null && includes.contains(s.getKey()))
    .sorted(Comparator.comparing(
        Map.Entry::getKey, Comparator.comparing(e -> (String) e))
    )
    .collect(Collectors.toMap(
        e -> (String) e.getKey(), 
        e -> (String) e.getValue(),
        (e1, e2) -> e2, 
        LinkedHashMap::new)
    );

我很想知道代码是否可以整理。

3 个答案:

答案 0 :(得分:5)

如何反转它并使用stream列表的includes代替?这样,您不必一直解压缩这些地图条目,您只需使用sorted,如果includes仅包含有效的属性,您可能甚至不需要{{1 }}。 (另外,在地图中查找比列表中的查找更快,但这可能并不重要。)

filter

答案 1 :(得分:2)

这里的“好”部分是Properties extends Hashtable<Object,Object>,它是问题的根源。不出所料,System.getProperties().entrySet()会返回Set<Map.Entry<Object, Object>>

因此,在进行过滤和排序之前,我们需要一个额外的映射操作将每个Entry<Object, Object>转换为Entry<String, String>

final Map<String, String> map = System.getProperties()
        .entrySet()
        .stream()
        .map(e -> new AbstractMap.SimpleEntry<>(e.getKey().toString(), e.getValue().toString()))
        .filter(e -> includes.contains(e.getKey()))
        .sorted(Comparator.comparing(AbstractMap.SimpleEntry::getKey))
        .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue));

方法引用看起来很模糊,因此最后2个操作将使用较短的lambda表达式:

.sorted(Comparator.comparing(e -> e.getKey()))
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));

另一种选择是迭代includes列表,该列表似乎小于System.getProperties()

final Properties properties = System.getProperties();
final Map<String, String> map2 = includes
        .stream()
        .filter(properties::containsKey)
        .sorted()
        .collect(Collectors.toMap(Function.identity(), properties::getProperty));

答案 2 :(得分:2)

我的意见是,过滤器4的所有属性(大约100)都不是最理想的。

我的建议是:

// hard coded here but (usually defined in a properties file)
final List<String> includes = Arrays.asList("java.version", "PID",
    "os.name", "user.country");

Map<String, String> systemMap = includes.stream()
    .collect(Collectors.toMap(e -> e,
        e -> System.getProperty(e)));

更新:排序版

final List<String> includes = Arrays.asList("java.version", "PID",
    "os.name", "user.country");     
Map<String, String> systemMap = includes.stream()
    .collect(Collectors.toMap(e -> e,
        e -> System.getProperty(e),
        (e1, e2) -> e2, 
        TreeMap::new));
return systemMap;