Estoy tratando de hacer un nuevo mapa de un otro mapa donde algunos de los valores son claves en otras entradas.
Ejemplo:
HashMap<String,String> testMap = new HashMap<>();
testMap.put("a","b");
testMap.put("b","d");
testMap.put("d","e");
testMap.put("e","f");
testMap.put("k","r");
Que necesito como resultado un nuevo mapa con este formato:
a->f
b->f
d->f
e->f
k->r
producedMap.put("a","f");
producedMap.put("b","f");
producedMap.put("d","f");
producedMap.put("e","f");
producedMap.put("k","r");
Mi código es que, aunque no parece dar el resultado verdadero.
public HashMap<String,String> getMatched(HashMap<String,String> correpondanceMap){
Collection<String> correpondanceKeys = correpondanceMap.keySet();
HashMap<String,String> newCorrepondanceMap= new HashMap<>();
correpondanceMap.entrySet().forEach(entry->{
if (correpondanceKeys.contains(entry.getValue())){
String newValue = entry.getValue();
String keyOfnewValue = correpondanceMap
.entrySet()
.stream()
.filter(entriii -> newValue.equals(entry.getValue()))
.map(Map.Entry::getKey).limit(1).collect(Collectors.joining());
newCorrepondanceMap.put(keyOfnewValue,correpondanceMap.get(newValue));
}
else
{
newCorrepondanceMap.put(entry.getKey(),entry.getValue());
}
});
newCorrepondanceMap.entrySet().forEach(entry-> System.out.println(entry.getKey() +" -- > " +entry.getValue()));
return newCorrepondanceMap;
}
Usted puede lograr que por alguna lógica recursión simple en una función de ayuda:
public static String findCorrespondingValue(Map<String, String> map, String key){
if(map.containsKey(key)){
return findCorrespondingValue(map, map.get(key));
}
return key;
}
Como dijo la lógica es muy simple, sólo comprobar si para un determinado key
existe un valor en lo dadomap
- Si es así entonces ejecutar la función de nuevo, pero esta vez con el
value
como el nuevokey
. - si no existe un mapeo podemos decir con seguridad que el
key
dado es el último valor en la cadena
Se puede llamar al método como este:
Map<String, String> testMap = ... // setup testMap
Map<String, String> result = new HashMap<>();
for (final Entry<String, String> entry : testMap.entrySet()) {
result.put(
entry.getKey(),
findCorrespondingValue(testMap, entry.getValue())
);
}
o si sucedió al uso de Java 8:
Map<String, String> result = testMap.entrySet().stream()
.collect(Collectors.toMap(
e -> e.getKey(), // or just Map.Entry::getKey
e -> findCorrespondingValue(e.getValue())
));
Usted, por supuesto, tendría que aplicar algún tipo de lógica para averiguar si tiene referencias cíclicas. P.ej:
a -> b
b -> f
f -> a
Lo que actualmente acaba de fallar con un StackOverflowError
.
Usted puede hacer esto también genérico si desea soportar múltiples tipos diferentes, no sólo String
:
public static <T> T findCorrespondingValue(Map<? extends T, ? extends T> map, T key){
if(map.containsKey(key)){
return findCorrespondingValue(map, map.get(key));
}
return key;
}