J'essaie de lire les propriétés du système Java au moment de l'exécution, filtre basé sur une includes liste (codée en dur ici mais normalement injectée via le fichier de propriétés) et finalement triée par clé et convertie en un Map<String, String>. C'est ce que j'ai proposé mais je ne sais pas si c'est la solution la plus élégante.

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)
    );

J'ai hâte de savoir si le code peut être rangé.

3
bobmarksie 26 nov. 2017 à 14:35

3 réponses

Meilleure réponse

Que diriez-vous de l'inverser et d'utiliser un stream de la liste includes à la place? De cette façon, vous n'avez pas à décompresser ces entrées de carte tout le temps, vous pouvez simplement utiliser sorted, et si includes ne comprend que des propriétés valides, vous n'aurez peut-être même pas besoin de filter . (De plus, la recherche dans la carte est plus rapide que la recherche dans la liste, mais cela n'a probablement pas beaucoup d'importance.)

Properties props = System.getProperties();
Map<String, String> systemMap = includes.stream()
    .filter(props::containsKey)
    .sorted()
    .collect(Collectors.toMap(s -> s, props::getProperty,
        (e1, e2) -> e2, 
        LinkedHashMap::new)
    );
5
tobias_k 26 nov. 2017 à 12:14

La "bonne" partie ici est celle Properties extends Hashtable<Object,Object> qui est une source de problèmes. Sans surprise, le System.getProperties().entrySet() renvoie un Set<Map.Entry<Object, Object>>.

Par conséquent, nous avons besoin d'une opération de mappage supplémentaire pour transformer chaque Entry<Object, Object> en Entry<String, String> avant de passer au filtrage et au tri:

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));

Les références de méthode semblent vagues, donc les 2 dernières opérations utiliseraient des expressions lambda plus courtes:

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

Une autre option consiste à parcourir la liste includes qui semble être plus petite que 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
Andrew Tobilko 26 nov. 2017 à 12:23

Mon avis, obtenir toutes les propriétés (environ 100) pour filtrer 4 est sous-optimal.

Ma proposition est:

// 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)));

UPDATE: version trié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;
2
Zabuzard 26 nov. 2017 à 13:29
47495683