You can obtain a Properties
instance of the JVM properties using System.getProperties()
; how would you go about using Java 8 code to print all properties to the console?
问题:
回答1:
One solution:
public final class Foo
{
private static void printProperty(final Object key, final Object value)
{
System.out.println(key + ": " + value);
}
public static void main(final String... args)
{
System.getProperties().forEach(Foo::printProperty);
}
}
Rundown:
Properties
extendsHashtable<Object, Object>
which itself implementsMap<Object, Object>
;Map
has a.forEach()
method whose argument is aBiConsumer
;BiConsumer
is a functional interface;- static method
printProperty()
of classFoo
happens to have the same signature as aBiConsumer<Object, Object>
: its "return value" isvoid
, its first argument isObject
, its second argument isObject
; - we can therefore use
Foo::printProperty
as a method reference.
A shorter version would be:
public final class ShorterFoo
{
public static void main(final String... args)
{
System.getProperties()
.forEach((key, value) -> System.out.println(key + ": " + value));
}
}
At runtime, this would not make a difference. Note the type inference in the second example: the compiler can infer that key
and value
are of type Object
. Another way to write this "anonymous lambda" would have been:
(Object key, Object value) -> System.out.println(key + ": " + value)
(not so) Side note: even though it is a little outdated, you really want to watch this video (yes, it's one hour long; yes, it is worth watching it all).
(not so) Side note 2: you may have noticed that Map
's .forEach()
mentions a default implementation; this means that your custom Map
implementations, or other implementations from external libraries, will be able to use .forEach()
(for instance, Guava's ImmutableMap
s). Many such methods on Java collections exist; do not hesitate to use these "new methods" on "old dogs".
回答2:
@fge has missed one very short version that admittedly depends on the toString
implementation of Map.Entry
.
public class VeryShortFoo {
public static void main(String... args) {
System.getProperties().entrySet().forEach(System.out::println);
}
}
- Here, the
entrySet
is streamed and eachMap.Entry
is printed with a reference toout.println
. Map.Entry
implementations oftoString
generally returngetKey() + "=" + getValue()
.
Here's another one I quite like.
public class ElegantFoo {
public static void main(String... args) {
System.getProperties().entrySet().stream()
.map(e -> e.getKey() + ": " + e.getValue())
.forEach(System.out::println);
}
}
- The
entrySet
is streamed again (this time explicitly with a call tostream
). Stream#map
performs a 1:1 conversion from elements of one type to elements of another. Here, it turns aStream<Map.Entry>
in to aStream<String>
.- The
Stream<String>
is printed.
回答3:
In Java 8, the Properties
class inherits a new method from HashTable
called forEach
. This new method accepts functions (functional interfaces) to be passed to it as arguments. To be more specific, it accepts the functional interface BiConsumer<T,U>
. This functional interface's functional method is accept(T t, U u)
. In Java 8, all functional interfaces can be written as Lambda expressions. Therefore, here is how we would display all properties in a Property
instance:
Properties vmProps = System.getProperties();
vmProps.forEach((t,u) -> System.out.println("Property: " + t + "\nValue: " + u + "\n"));
回答4:
Sorted by key (makes it useful)
printProperties(System.getProperties());
public static void printProperties(Properties properties) {
new TreeSet<>(properties.keySet()).forEach((k) -> {
System.out.println(k + " : " + properties.get(k));
});
}
回答5:
System.getProperties().list(System.out);