Tengo Lista de historias. Usando única property(id)
falta que a la palabra clave a cobro revertido y la focalización como lista de valores. ¿Puedo hacer esto con MultiMap
? ¿O hay otra biblioteca para este?
[{
id = 1,
title = Onboarding,
keyword = new joinee,
targeting = finance
}, {
id = 1,
title = Onboarding,
keyword = training,
targeting = HR
}]
La salida deseado tiene como esto:
{
id = 1,
title = Onboarding,
keyword = [new joinee,training], //may be keywords - plural
targeting = [HR,finance]
}
Probar mi código de tratado de la siguiente manera:
package prac;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class JavaPrac {
public static void main(String[] args) {
Multimap<Integer, Map> multiMap = ArrayListMultimap.create();
List<Map> stories=new ArrayList();
Map story1=new HashMap();
story1.put("id", 1);
story1.put("title", "Onboarding");
story1.put("keyword","new joinee");
story1.put("targeting","finance");
Map story2=new HashMap();
story2.put("id", 1);
story2.put("title", "Onboarding");
story2.put("keyword","training");
story2.put("targeting","HR");
stories.add(story1);
stories.add(story2);
System.out.println(stories);
stories.forEach((story) -> {
multiMap.put((Integer) story.get("id"), story);
});
}
}
Un multimap sólo puede almacenar varios valores por clave, pero lo que desea es combinar esos valores múltiples de manera que se obtiene un elemento que tiene el mismo ID y el título, así como una colección de palabras clave y la información de orientación. Por lo tanto, probablemente sería mejor tener ya sea algo así MultiStory
o ya tiene Story
contener esas colecciones.
Me gustaría sugerir el uso de objetos propios en lugar de sólo los mapas, pero con mapas y Java 8 lambdas que podría utilizar compute()
, etc para construir mapas que contienen colecciones y combinar mapas que no lo hacen.
Aquí está un ejemplo de cómo se haría con los mapas. Tenga en cuenta que esto es muy mal estilo y un ejemplo usando POJOs adecuados seguirá:
Exención de responsabilidad: ejemplo basado en el código de la OP, no se recomienda (texto leído anteriormente)
//Problem 1: we don't know the type of the values, i.e. we could put anything for "id" etc.
Map<String, Object> story1=new HashMap<>();
story1.put("id", 1);
story1.put("title", "Onboarding");
story1.put("keyword","new joinee");
story1.put("targeting","finance");
Map<String, Object> story2=new HashMap<>();
story2.put("id", 1);
story2.put("title", "Onboarding");
story2.put("keyword","training");
story2.put("targeting","HR");
List<Map<String, Object>> stories=new ArrayList<>();
stories.add(story1);
stories.add(story2);
Map<Integer, Map<String, Object>> combined = new HashMap<>();
stories.forEach((story) -> {
//Problem 2: because we don't know the type of the values we need a lot of nasty casts
Map<String, Object> combinedStory = combined.computeIfAbsent( (Integer)story.get( "id" ), k -> new HashMap<String, Object>() );
combinedStory.put("id", story.get( "id" ) );
combinedStory.put("title", story.get( "title" ) );
//Problem 3: the combined map would look a lot like your "story" maps but would contain different types
((List<String>)combinedStory.computeIfAbsent( "keyword", v -> new List<String>() )).add( (String)story.get("keyword") );
((List<String>)combinedStory.computeIfAbsent( "targeting", v -> new List<String>() )).add( (String)story.get("targeting") );
});
El uso de POJOs
He aquí un ejemplo muy simplificado de cómo se haría con objetos propios de Java (POJO). Tenga en cuenta que los están destinados a parecerse a su código tanto como sea posible y hay un montón de otras cuestiones, pero abordando los que serían demasiado aquí y mejor código diseñado sería mucho más grande y probablemente más difícil de entender - después de todo es sólo la intención se puede mostrar la diferencia.
En primer lugar vamos a definir nuestras clases (para simplificar hice el público campos, usted normalmente no hace eso):
class Story {
public final int id;
public String title;
public String keyword;
public String targeting;
public Story(int storyId) {
id = storyId ;
}
}
class MultiStory {
public final int id;
public String title;
public Set<String> keywords = new HashSet<>();
public Set<String> targetingInfo = new HashSet<>();
public MultiStory( int storyId ) {
id = storyId ;
}
}
A continuación, vamos a reiterar el código anterior:
Story story1=new Story( 1 );
story1.title = "Onboarding";
story1.keyword = "new joinee";
story1.targeting = "finance";
Story story2=new Story( 1 );
story2.title = "Onboarding";
story2.keyword = "training";
story2.targeting = "HR";
List<Story> stories=new ArrayList<>();
stories.add(story1);
stories.add(story2);
Map<Integer, MultiStory> combined = new HashMap<>();
stories.forEach((story) -> {
MultiStory multiStory = combined.computeIfAbsent( story.id, v -> new MultiStory( story.id ) );
multiStory.title = story.title;
multiStory.keywords.add( story.keyword );
multiStory.targetingInfo.add( story.targeting );
});
Como se puede ver, no hay moldes necesarios y está claro qué campos están disponibles (aunque no necesariamente llena), que hace que sea más fácil de razonar acerca de los errores de código y al contado (el compilador puede ayudar mucho aquí, que no podía para de el ejemplo que utiliza mapas).