I have POJO List<TravelRequestDTO> and I want to group and create filtered List<TravelRequestDTO> if leavingFrom,goingTo,onwarDate,returnDate are same add passenger to same object
Example :
Passanger, onWard, return, leavingFrom, goingTo
A, 1-2-20, 3-2-20, BLR, PUNE
B, 1-2-20 , 3-2-20, BLR, PUNE
final List<TravelRequestDTO> should contain :
Passanger, onWard, return, leavingFrom, goingTo
A,B 1-2-20 3-2-20 BLR PUNE
public class TravelRequestDTO {
private List<Pax> passangers;
private String leavingFrom;
private String goingTo;
private String onwarDate;
private String onwardTime;
private String returnDate;
private String returnTime;
private SegmentTypeEnum segmentType;
private TravelModeEnum travelMode;
private String purposeOfVisit;
}
public class Pax{
private String name;
private String age;
private String mobile;
}
If you need older java version, than you can do like this:
Map<Object, List<TravelRequestDTO>> hashMap = new HashMap<Object, List<TravelRequestDTO>>();
for (TravelRequestDTO value: initList) {
List<Object> key = Arrays.asList(value.getOnWard(),value.getReturn(),value.getLeavingFrom(),value.getGoingTo());
if (!hashMap.containsKey(key)) {
List<TravelRequestDTO> list = new ArrayList<TravelRequestDTO>();
list.add(value);
hashMap.put(key, list);
} else {
hashMap.get(key).add(value);
}
}
Check this question for other solution.
It is only half way to what you want. After that you have to extract final result from this map. Or you can do it in one step:
Map<Object, TravelRequestDTO> hashMap = new HashMap<Object, TravelRequestDTO>();
for (TravelRequestDTO value: initList) {
List<Object> key = Arrays.asList(value.getOnWard(),value.getReturn(),value.getLeavingFrom(),value.getGoingTo());
if (!hashMap.containsKey(key)) {
TravelRequestDTO item = value; // pass first value or copy it to new
hashMap.put(key, item);
} else {
hashMap.get(key).getPassangers().addAll(value.getPassangers());
}
}
List<TravelRequestDTO> result = new ArrayList<>(hashMap.values());
you can use the below code to get a List of TravelRequestDTO objects based on properties.
Function<TravelRequestDTO, List<Object>> compositeKey = travelRecord ->
Arrays.<Object>asList(travelRecord.getOnWard(),travelRecord.getReturn(),travelRecord.getLeavingFrom(),travelRecord.getGoingTo());
Map<Object, List<TravelRequestDTO>> map =
people.collect(Collectors.groupingBy(compositeKey, Collectors.toList()));
Related
I have class let's say CheeseMojo having various fields as follow:
public class CheeseMojo {
private String recipies = "Recipies";
private int age;
private String name;
private int submissionId;
//getter/setter
}
Now I want to sort it based on submissionId using Collectors.groupingBy function, then below code snippet will do the job
Map<Integer,List<CheeseMojo>> map = new HashMap<>();
map = cheeseMojos.stream().collect(Collectors.groupingBy(CheeseMojo::getSubmissionId));
And the output will be something like below:
{1=[CheeseMojo#111111],2=[CheeseMojo#222222]}
But I want my output something like below:
{"Recipies1"=[CheeseMojo#111111],"Recipies2"=[CheeseMojo#222222]}
Please help
Why don't you just map the key either before collecting (lets say by creating an instance of a wrapper class that has
public class CheeseMojoWrapper {
private final String id;
private final CheeseMojo wrapped;
public CheeseMojoWrapper(CheeseMojo toWrap) {
id = "Recipe" + toWrap.getId();
wrapped = toWrap;
}
}
or using a stream on the entrySet() of your resulting map...
I have converted this JSON to Hashmap
http://www.mocky.io/v2/5d0dc72d3400008c00ca4a62
I have nested Hashmap and I wanted to convert it to ArrayList
Map<String, Bank> stringBankMap = getValues();
I want to get all the data from stringBankMap and add to the list. I want also the key to the hashmap to also will be imported on the list as a guide.
Here is Bank class
public class Bank {
private String guid;
private String title;
private long date;
private String logo;
private HashMap<String, HashMap<String, BankList>> list;
}
Here is BankList class
public class BankList {
private double buy;
private double sell;
private String currency;
}
What I tried
for(Map.Entry<String, Bank> entry1 : stringBankMap.entrySet()) {
Bank newBank = new Bank(entry1.getKey());
Bank bank = entry1.getValue();
newBank.setDate(bank.getDate());
newBank.setLogo(bank.getLogo());
newBank.setTitle(bank.getTitle());
List<BankList> bankListList = new ArrayList<>();
for(Map.Entry<String, HashMap<String, BankList>> entry2 : bank.getList().entrySet()) {
HashMap<String, BankList> map = entry2.getValue();
for (Map.Entry<String, BankList> entry3 : map.entrySet()) {
BankList newBankList = new BankList(entry3.getKey());
BankList bankList = entry3.getValue();
newBankList.setBuy(bankList.getBuy());
newBankList.setSell(bankList.getSell());
bankListList.add(newBankList);
}
}
bankArrayList.add(newBank);
}
But I don't understand why I am getting an exception
Please suggest me other algorithms if you can
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to core.model.Bank
you can do it this way : make a class node with data members String key and Bank value like
`class Node{
String key;
Bank value;
Node(String k,Bank val){
key=k;
value=val;
}
}`
then make an ArrayList of class Node ,then add elements to the list as [list name].add(new Node([pass key and value here]) by traversing through the map like here
and then you can traverse the list in the desired order and get your elements by [arraylist name].get(index).key or [arraylist name].get(index).value
I often find myself in a situation where I need to create a Map of objects from a Set or List.
The key is usually some String or Enum or the like, and the value is some new object with data lumped together.
The usual way of doing this, for my part, is by first creating the Map<String, SomeKeyValueObject> and then iterating over the Set or List I get in and mutate my newly created map.
Like the following example:
class Example {
Map<String, GroupedDataObject> groupData(final List<SomeData> list){
final Map<String, GroupedDataObject> map = new HashMap<>();
for(final SomeData data : list){
final String key = data.valueToGroupBy();
map.put(key, GroupedDataObject.of(map.get(key), data.displayName(), data.data()));
}
return map;
}
}
class SomeData {
private final String valueToGroupBy;
private final Object data;
private final String displayName;
public SomeData(final String valueToGroupBy, final String displayName, final Object data) {
this.valueToGroupBy = valueToGroupBy;
this.data = data;
this.displayName = displayName;
}
public String valueToGroupBy() {
return valueToGroupBy;
}
public Object data() {
return data;
}
public String displayName() {
return displayName;
}
}
class GroupedDataObject{
private final String key;
private final List<Object> datas;
private GroupedDataObject(final String key, final List<Object> list) {
this.key = key;
this.datas = list;
}
public static GroupedDataObject of(final GroupedDataObject groupedDataObject, final String key, final Object data) {
final List<Object> list = new ArrayList<>();
if(groupedDataObject != null){
list.addAll(groupedDataObject.datas());
}
list.add(data);
return new GroupedDataObject(key, list);
}
public String key() {
return key;
}
public List<Object> datas() {
return datas;
}
}
This feels very unclean. We create a map, and then mutate it over and over.
I've taken a liking to java 8s use of Streams and creating non-mutating data structures (or rather, you don't see the mutation). So is there a way to turn this grouping of data into something that uses a declarative approach rather than the imperative way?
I tried to implement the suggestion in https://stackoverflow.com/a/34453814/3478016 but I seem to be stumbling. Using the approach in the answer (the suggestion of using Collectors.groupingBy and Collectors.mapping) I'm able to get the data sorted into a map. But I can't group the "datas" into one and the same object.
Is there some way to do it in a declarative way, or am I stuck with the imperative?
You can use Collectors.toMap with a merge function instead of Collectors.groupingBy.
Map<String, GroupedDataObject> map =
list.stream()
.collect(Collectors.toMap(SomeData::valueToGroupBy,
d -> {
List<Object> l = new ArrayList<>();
l.add(d.data());
return new GroupedDataObject(d.valueToGroupBy(), l);
},
(g1,g2) -> {
g1.datas().addAll(g2.datas());
return g1;
}));
The GroupedDataObject constructor must be made accessible in order for this to work.
If you avoid the GroupedDataObject and simply want a map with a key and a list you can use Collectors.groupingBy that you have been looking into.
Collectors.groupingBy will allow you to do this:
List<SomeObject> list = getSomeList();
Map<SomeKey, List<SomeObject>> = list.stream().collect(Collectors.groupingBy(SomeObject::getKeyMethod));
This will require SomeKey to have proper implementations of equals and hashValue
Sometimes streams are not the way to go. I believe this is one of those times.
A little refactoring using merge() gives you:
Map<String, MyTuple> groupData(final List<SomeData> list) {
Map<String, MyTuple> map = new HashMap<>();
list.forEach(d -> map.merge(d.valueToGroupBy(), new MyTuple(data.displayName(), data.data()),
(a, b) -> {a.addAll(b.getDatas()); return a;});
Assuming a reasonable class to hold your stuff:
class MyTuple {
String displayName;
List<Object> datas = new ArrayList<>();
// getters plus constructor that takes 1 data and adds it to list
}
I wanted to create a table/list in Java, and I wonder what is the best way to handle it.
The table should have a structure like this:
Term propertyList entitiesList
a1 p1=1, p2=2, p3=2 T1,T2
a2 p5=0, p4=5 ,p3=3 T2,T1
a3 p1=1 ,p4=3, p3=9 T3,T1,T2
...
a10
I have a list with exactly 10 terms, and for every term there is a list of properties (deep with key and value), and the properties can be either in one or more entities.
I need some help on how to create it, e.g. should I use list, map, collection etc.
How can I add hardcoded values to them as literals in the code, and what is the best way to read data from it, taking into account performance, given that later I will need to use this for every entity and find the related properties that participate in every term.
first off Create Term class.
So you have list of Terms: List<Term>
Term class
public class Term {
private String mName = "";
private Map<String, Integer> mPropertyMap = new LinkedHashMap<String, Integer>();
private List<String> mEntitiesList = new ArrayList<String>();
public Term(String name) {
mName = name;
}
public void generate(Map<String, Integer> propertyMap, List<String> entitiesList) {
mPropertyMap = propertyMap;
mEntitiesList = entitiesList;
}
public Map<String, Integer> getPropertyMap() {
return mPropertyMap;
}
public void setPropertyMap(Map<String, Integer> propertyMap) {
this.mPropertyMap = propertyMap;
}
public List<String> getEntitiesList() {
return mEntitiesList;
}
public void setEntitiesList(List<String> entitiesList) {
this.mEntitiesList = entitiesList;
}
public String getName() {
return mName;
}
public void setmName(String name) {
this.mName = name;
}
}
Main Class
public class MyClass {
private List<Term> mTermList = null;
private void init() {
mTermList = new ArrayList<Term>();
}
private void addSomeTerm() {
Map<String, Integer> propertyMap = new LinkedHashMap<String, Integer>();
propertyMap.put("p1", 1);
propertyMap.put("p2", 2);
propertyMap.put("p3", 3);
List<String> entitiesList = new ArrayList<String>();
entitiesList.add("T1");
entitiesList.add("T2");
Term term = new Term("a1");
term.generate(propertyMap, entitiesList);
mTermList.add(term);
}
private String printTerms() {
StringBuilder buff = new StringBuilder();
for(Term currTerm : mTermList){
buff.append(currTerm.getName()).append(" ");
Map<String, Integer> propertyMap = currTerm.getPropertyMap();
Set<String> sets = propertyMap.keySet();
Iterator<String> itr = sets.iterator();
String key = null;
Integer value = null;
while(itr.hasNext()){
key = itr.next();
value = propertyMap.get(key);
buff.append(key + "=" + value).append(",");
}
buff.setLength(buff.length()-1); // remove last ','
buff.append(" ");
List<String> entitiesList = currTerm.getEntitiesList();
for(String str : entitiesList){
buff.append(str).append(",");
}
buff.setLength(buff.length()-1); // remove last ','
}
return buff.toString();
}
/**
* #param args
*/
public static void main(String[] args) {
MyClass m = new MyClass();
m.init();
m.addSomeTerm();
System.out.println(m.printTerms());
}
}
Output:
a1 p1=1,p2=2,p3=3 T1,T2
It looks like you could have the following structure:
class Term {
String id;
Map<String, String> properties;
List<Entity> entities; // (or Set<Entity> if no duplicates are allowed)
}
But it's not very clear what you mean by "deep" and by "the properties can be either in one or more entities".
how do i access an array by its keys in java
In this case i want the structure to be like this,
options[{"value":"0","label":"zero"},{"value":"1","label":"one"},
{"value":"2","label":"two"}]
Here if i want to access options[1].value should give me 1 and options[2].label should give me two.
How can i achieve this with Map<string><string[]>?
Also Can i pass "options" array as one of the keys in my hash map
protected Map<String, String[]> getValueProperties(int view, Field field) {
Map<String, String> properties = new HashMap<String,String[]>();
properties.put("options", []);
return properties
}
You should create a new class representing your object:
public final class MyObject {
private String value;
private String label;
public MyObject(String label, String value) { ... }
public String getValue() { ... }
public String getLabel() { ... }
}
And then create a list of MyObject:
final List<MyObject> objects = new ArrayList<>();
objects.add(new MyObject("zero", "0");
objects.add(new MyObject("one", "1");
objects.add(new MyObject("two", "2");
Then you can access the objects values directly: objects.get(0).getValue();
Create a class as follows
class Entry
{
int value;
string label;
public Entry(int val, string lbl)
{
this.value = val;
this.label = lbl;
}
}
Now create you options array as follows:
Entry[] options = new Entry[3];
options[0] = new Entry(0, "zero");
options[1] = new Entry(1, "one");
options[2] = new Entry(2, "two");
if i want to access options[1].value should give me 1 and options[2].label should give me two
Now, options[1].value will give you 1.