2017-02-16 15 views
4

Например, если карта, как показано ниже:Стиль потока java8 для извлечения внутренней части карты через список полей?

{ 
    "k1": { 
    "k2": { 
     "k3": { 
     "k4": "v" 
     } 
    } 
    } 
} 

и список полей ["k1","k2","k3"], мне нужно, чтобы получить часть {"k4": "v"}.

Ниже мой код java7 стиле:

// Ignore the map building code. 
Map map1 = new HashMap(); 
Map map2 = new HashMap(); 
Map map3 = new HashMap(); 
Map map4 = new HashMap(); 
map4.put("k4", "v"); 
map3.put("k3", map4); 
map2.put("k2", map3); 
map1.put("k1", map2); 
Map map = map1; 
System.out.println(map); //=> {k1={k2={k3={k4=v}}}} 

// Code to be transformed to java8 style 
List<String> fields = Arrays.asList("k1", "k2", "k3"); 
for(String field: fields) { 
    map = (Map) map.get(field); 
} 
System.out.println(map); //=> {k4=v} 

Тогда как преобразовать выше кода в Java 8 стиле потока?

ответ

8

Я не думаю, что есть какая-либо польза в преобразовании этого в функциональный стиль; петля прекрасна и точно выражает то, что вы делаете.

Но для полноты картины, вы можете сделать это следующим образом:

map = (Map)fields.stream() 
    .<Function>map(key -> m -> ((Map)m).get(key)) 
    .reduce(Function.identity(), Function::andThen).apply(map); 

Это преобразует каждый ключ к функции, способной делать карту поиск этого ключа, а затем сочиняет их к одной функции, которая применяется вам map. Перенос операции в эту точку необходим, поскольку функции не могут изменять локальные переменные.

Это также можно сплавить map операции с reduce операции, что позволяет исключить явный тип (<Function>):

map = (Map)fields.parallelStream() 
.reduce(Function.identity(), (f, key)->f.andThen(m->((Map)m).get(key)), Function::andThen) 
.apply(map); 

Может быть, вы теперь признают, что это задача, для которой простой for петля лучше подходит.

+3

@tobias_k: это отлично работает параллельно, как превращение потока в параллельном бы только распараллелить функцию состав, в то время как окончательный 'apply' вызов всегда последователен (и не зависят от потока). – Holger

+3

@ Голосовать, ваши ответы заставляют меня головокружение. это очень мило – Eugene

0

Как насчет?

fields.stream().reduce(map1, (m, key) -> (Map) m.get(key), (a, b) -> a);