I am trying to query a property of all items in a map.
I can do it with a collection, but it does not work for map.
I have tries many variation, but did not find a way to get all ids of objects in map.
See complete code example below.
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.jxpath.JXPathContext;
public class TestMap {
public static void main(String[] args) {
Person p = createPerson(1);
p.foes = new HashMap<>();
p.foes.put("a", createPerson(2));
p.foes.put("b", createPerson(3));
p.friends = new ArrayList<>();
p.friends.add(createPerson(4));
p.friends.add(createPerson(5));
//works
Iterator<Object> friendsId = JXPathContext.newContext(p).iterate("friends/id");
friendsId.forEachRemaining(o -> System.out.println(o));
// works
Iterator<Object> foesId = JXPathContext.newContext(p).iterate("foes/a/id");
foesId.forEachRemaining(o -> System.out.println(o));
// does not works :(
foesId = JXPathContext.newContext(p).iterate("foes/id");
foesId.forEachRemaining(o -> System.out.println(o));
}
private static Person createPerson(Integer id) {
Person p = new Person();
p.setId(id);
return p;
}
public static class Person {
private Integer id;
private List<Person> friends;
private Map<String, Person> foes;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public List<Person> getFriends() {
return friends;
}
public void setFriends(List<Person> friends) {
this.friends = friends;
}
public Map<String, Person> getFoes() {
return foes;
}
public void setFoes(Map<String, Person> foes) {
this.foes = foes;
}
}
}
https://commons.apache.org/proper/commons-jxpath/users-guide.html#Map_Element_Access
found it : "foes/*/id" works.
A bit obvious
Related
I have an ArrayList of transactions for a database in java. Each query has some weight associated with it. I want to execute that transaction that many number of times.
For eg putting 1 transaction in JSON format:-
{
"transaction": {
"name": "NewOrder",
"weight": 45,
"queries": [
{
"query": "select * from account where id > ? and balance > ?",
"bindParams": [
{
"utilityFunction": {
"name": "randomString",
"params": [
{
"minLen": 8,
"maxLen": 16
}
]
}
},
{
"utilityFunction": {
"name": "randomInteger",
"params": [
{
"minValue": 100000,
"maxLen": 100000
}
]
}
}
]
}
I have similar transactions with weights which add upto 100.
I now want to get the id of this transaction from the arraylist of transactions based on its weight.
For eg(transaction names and their weight):-
new order :-45(weight)
stockpurchase:- 30(weight)
newitems :- 15(weight)
deliveryitems :- 10 (weight)
I created an arrayList of integers which stores the sum till that index of transaction :-
[45,75,90,100]
Now I am thinking on invoking a random number[1-100] and get the index that lies closest to it to get the index from the arrayList of transactions.
Is this implementation correct or is there a more efficient way of doing this?
you need to convert your schema to POJO. like this
package com.example;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Generated;
public class BindParam {
private UtilityFunction utilityFunction;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
public UtilityFunction getUtilityFunction() {
return utilityFunction;
}
public void setUtilityFunction(UtilityFunction utilityFunction) {
this.utilityFunction = utilityFunction;
}
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
package com.example;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Generated;
public class Param {
private Integer minLen;
private Integer maxLen;
private Integer minValue;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
public Integer getMinLen() {
return minLen;
}
public void setMinLen(Integer minLen) {
this.minLen = minLen;
}
public Integer getMaxLen() {
return maxLen;
}
public void setMaxLen(Integer maxLen) {
this.maxLen = maxLen;
}
public Integer getMinValue() {
return minValue;
}
public void setMinValue(Integer minValue) {
this.minValue = minValue;
}
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
package com.example;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Generated;
public class Query {
private String query;
private List<BindParam> bindParams = null;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
public List<BindParam> getBindParams() {
return bindParams;
}
public void setBindParams(List<BindParam> bindParams) {
this.bindParams = bindParams;
}
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
package com.example;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Generated;
#Generated("jsonschema2pojo")
public class Transaction {
private String name;
private Integer weight;
private List<Query> queries = null;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
public List<Query> getQueries() {
return queries;
}
public void setQueries(List<Query> queries) {
this.queries = queries;
}
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
package com.example;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Generated;
#Generated("jsonschema2pojo")
public class UtilityFunction {
private String name;
private List<Param> params = null;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Param> getParams() {
return params;
}
public void setParams(List<Param> params) {
this.params = params;
}
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
package com.example;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Generated;
public class WrapperClass {
private Transaction transaction;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
public Transaction getTransaction() {
return transaction;
}
public void setTransaction(Transaction transaction) {
this.transaction = transaction;
}
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
public class Main() {
public static void main(String[] args) {
//assume that you collect data from getValue()
List<WrapperClass> wrappers = getValue();
for(WrapperClass wrapper : wrappers) {
Transaction transaction = wrapper.getTransaction();
int weight = transaction.getWeight();
}
}
}
you can use JSONSchema2POJO to generate model from json.
This question already has answers here:
java.util.ConcurrentModificationException thrown when adding to List
(2 answers)
Closed 1 year ago.
I have a list of concrete objects. While iterating over this list, I'm trying to update an object from it by adding values and I'm getting of course a ConcurentModificationException:
What are my alternatives? Thank you and appreciate the help. I'm using Java 11.
import lombok.Data;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
public class Test {
public static void main(String[] args) throws IOException {
List<Person> myList = new ArrayList<>();
List<Hobby> hobbies = new ArrayList<>();
Hobby h1 = new Hobby("SKI");
Hobby h2 = new Hobby("reading");
hobbies.add(h1);
hobbies.add(h2);
Person p = new Person("R", hobbies);
Person p1 = new Person("M", hobbies);
myList.add(p);
myList.add(p1);
myList
.forEach(currentElement -> {
if (Objects.isNull(currentElement.getHobbies())) {
currentElement.setHobbies(Collections.singletonList(new Hobby("NOTHING")));
} else {
currentElement.getHobbies()
.forEach(hobby -> {
if (hobby.getMyHobby().equals("SKI")) {
currentElement.getHobbies().add(new Hobby("SAILING"));
} else {
hobby.getMyHobby().toLowerCase();
}
});
}
});
}
#Data
static
class Person {
String name;
List<Hobby> hobbies;
public Person(String name, List<Hobby> hobbies) {
this.name = name;
this.hobbies = hobbies;
}
}
#Data
static class Hobby {
String myHobby;
public Hobby(String myHobby) {
this.myHobby = myHobby;
}
}
}
You can iterate over the indexes instead:
for (int i = 0; i < currentElement.getHobbies().size(); i++) {
Hobby hobby = currentElement.getHobbies().get(i);
if (hobby.getMyHobby().equals("SKI")) {
currentElement.getHobbies().add(new Hobby("SAILING"));
} else {
hobby.getMyHobby().toLowerCase(); // sic
}
}
public class Person {
private long id;
private String name;
}
List<Person> persons= Arrays.asList(new Person(1,"Alex"),new Person(2,"Danny"),new Person(3,"Frank"));
List<Long>ids=Arrays.asList(1L,5L);
How to effectively remove objects from the list of persons whose id is on the list of ids??
The best way for me is to use streams.
You can use Stream filter to filter the list based on your criteria.
List<Person> filteredPersons = persons.stream()
.filter(person -> !ids.contains(person.id))
.collect(Collectors.toList());
This would be a good place to get you started on Streams
https://dzone.com/articles/how-to-use-map-filter-collect-of-stream-in-java-8
If you want to alter the original list in-place, rather than making a copy, you can use the removeIf() method with a suitable predicate:
persons.removeIf(p -> !ids.contains(p.id));
Also note that using a Set for the ids collection will make your intent more obvious and probably perform better as the set of identifiers grows large.
please check below code :-
package design.pattern;
public class Person {
private long id;
private String name;
public Person(long id, String name) {
super();
this.id = id;
this.name = name;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package design.pattern;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Test{
public static void main(String[] args) {
List<Person> persons= new ArrayList<Person>(Arrays.asList(new Person(1,"Alex"),new Person(2,"Danny"),new Person(3,"Frank")));
List<Long>ids=Arrays.asList(1L,5L);
for (int i = 0; i < persons.size(); i++) {
Long id = persons.get(i).getId();
System.out.println(id);
if (ids.contains(id)) {
System.out.println(id);
persons.remove(persons.get(i));
}
}
for(Person person:persons)
System.out.println("Resultant List"+person.getName());
}
}
hope this will be helpful for you
I have a scenario to get a child hierarchy structure of a field till parent for doing field level validations.
Can someone provide some solution.
Pojo classes
Student.java
package com.poc.next.validations;
import java.util.ArrayList;
import java.util.List;
public class Student {
private String studentName;
private List<Subject> subjects;
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public List<Subject> getSubjects() {
if (subjects == null) {
return new ArrayList<>();
}
return subjects;
}
public void setSubjects(List<Subject> subjects) {
this.subjects = subjects;
}
}
Subject.java
package com.poc.next.validations;
import java.util.ArrayList;
import java.util.List;
public class Subject {
private String subjectName;
private List<RevisionMarks> revisionMarks;
public String getSubjectName() {
return subjectName;
}
public void setSubjectName(String subjectName) {
this.subjectName = subjectName;
}
public List<RevisionMarks> getRevisionMarks() {
if (revisionMarks == null) {
return new ArrayList<>();
}
return revisionMarks;
}
public void setRevisionMarks(List<RevisionMarks> revisionMarks) {
this.revisionMarks = revisionMarks;
}
}
RevisionMarks.java
package com.poc.next.validations;
public class RevisionMarks {
private Integer mark;
private String revision;
public Integer getMark() {
return mark;
}
public void setMark(Integer mark) {
this.mark = mark;
}
public String getRevision() {
return revision;
}
public void setRevision(String revision) {
this.revision = revision;
}
}
Now we are adding a validation to check whether the given mark in RevisionMarks class in valid or not. if it is equal to zero I have to add it to error dto and send it back to UI. The challenge here is i have to provide the field name dynamic in hierarchy like "subjects[0].revisionMarks[0].mark".
Main class
RevisionValidation.java
package com.poc.next.validations;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class RevisionValidation {
public static void main(String[] args) {
Student student = populateStudentData();
Iterator<Subject> iterator = student.getSubjects().iterator();
while (iterator.hasNext()) {
Subject subject = (Subject) iterator.next();
RevisionMarks revisionMarks = subject.getRevisionMarks().get(0);
System.out.println(revisionMarks.getMark());
if (revisionMarks.getMark() == 0) {
ErrorDTO errorDTO = new ErrorDTO(true, "Invalid Marks", "Error", "subjects[0].revisionMarks[0].mark",
"invalid_mark");
System.out.println(errorDTO);
}
}
}
private static Student populateStudentData() {
List<RevisionMarks> revisionMarks = new ArrayList<>();
RevisionMarks revisionMark = new RevisionMarks();
revisionMark.setMark(0);
revisionMark.setRevision("Test 1");
revisionMarks.add(revisionMark);
List<Subject> subjects = new ArrayList<>();
Subject subject = new Subject();
subject.setSubjectName("CS");
subject.setRevisionMarks(revisionMarks);
subjects.add(subject);
Student student = new Student();
student.setStudentName("Sample");
student.setSubjects(subjects);
return student;
}
}
How can I dynamically create the fieldpath like "subjects[0].revisionMarks[0].mark".
Any suggestions are welcome. Thanks in advance.
Use a counter:
int counter = 0;
Iterator<Subject> iterator = student.getSubjects().iterator();
while (iterator.hasNext()) {
Subject subject = (Subject) iterator.next();
RevisionMarks revisionMarks = subject.getRevisionMarks().get(0);
System.out.println(revisionMarks.getMark());
if (revisionMarks.getMark() == 0) {
ErrorDTO errorDTO = new ErrorDTO(true, "Invalid Marks", "Error", "subjects[" + counter + "].revisionMarks[0].mark",
"invalid_mark");
System.out.println(errorDTO);
}
++counter;
}
I would suggest to use JSR3 validation instead of reinventing wheel.
https://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/
You can add necessary annotations for each field in your POJO and add #Valid annotation to let validator check nested POJO objects.
The link
https://www.beyondjava.net/blog/how-to-invoke-jsr-303-bean-validation-programmatically/ shows how to call the validator programmatically.
With the validation you can provide any messages and localize them, and the xpaths are built automatically pointing problems in POJO or nested POJOs.
What I am doing is getting elements from a map and adding them onto a JList to display on a GUI. I want to know how to sort the names alphabetically.
private void refreshShopsList() {
gameShopsJList.setModel(new javax.swing.AbstractListModel<String>() {
public int getSize() {
return ShopsLoader.getShops().size();
}
public String getElementAt(int i) {
return getShopByIndex(i).getName();
}
});
}
private Shop getShopByIndex(int index) {
Iterator<Entry<String, Shop>> it = ShopsLoader.getShops().entrySet().iterator();
int count = -1;
while(it.hasNext()) {
Entry<String, Shop> entry = it.next();
count++;
if (count == index)
return entry.getValue();
}
return null;
}
/**
* The map of the shops
*/
private static final Map<String, Shop> shops = new HashMap<String, Shop>();
public static Map<String, Shop> getShops() {
return shops;
}
Here is a little example, which sorts your shop names.
The ShopComparator class does the sorting task:
package model;
import java.util.Comparator;
public class ShopComparator implements Comparator<Shop> {
#Override
public int compare(Shop o1, Shop o2) {
return o1.getName().compareTo(o2.getName());
}
}
The Shop class, as simple as possible:
package model;
public class Shop {
private int id;
private String name;
public Shop(int id, String name) {
super();
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And the main app:
package model;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;
public class App {
public static void main(String[] args) {
Map<String, Shop> shops = new HashMap<String, Shop>();
Shop s1 = new Shop(1, "Apus Drugstore");
Shop s2 = new Shop(2, "DM");
Shop s3 = new Shop(3, "Kaufhof");
Shop s4 = new Shop(4, "Moes Traverne");
shops.put("one", s3);
shops.put("two", s4);
shops.put("three", s1);
shops.put("four", s2);
for(Shop s : shops.values()) {
System.out.println(s.getName());
}
ShopComparator sc = new ShopComparator();
TreeSet<Shop> sortedShops = new TreeSet<>(sc);
sortedShops.addAll(shops.values());
for(Shop s : sortedShops) {
System.out.println(s.getName());
}
}
}
First output, unsorted:
Moes Traverne
Kaufhof
Apus Drugstore
DM
and the sorted output.
Apus Drugstore
DM
Kaufhof
Moes Traverne
Algorithm:
get all values from JList, convert them to strings, store in array
sort the array
set new values to JList.
code:
JList jl = new JList(new Object[]{4.5,1,"Hi!"});
ListModel model = jl.getModel();
String[] strings = new String[model.getSize()];
for(int i=0;i<strings.length;i++){
strings[i]=model.getElementAt(i).toString();
}
Arrays.sort(strings);
jl.setListData(strings);
see about Comparator if you need to sort array in any other order.