I have a mapper method which takes list of entities called Claim iterates over them and maps to CompensationDTO and adds to list, but entity can contain lists of children entities which type is also Claim and those children can also contain list of Claims, so to iterate over them all is best to use recursion but i'm not sure how it should be written
private List<CompensationDTO> mapToDTO(List<Claims> claims) {
List<CompensationsDTO> compensations = new ArrayList<>();
if (claims.isEmpty()) {
return new ArrayList<>();
}
for (Claim claim : claims) {
CompensationDTO compensationDTO = new CompensationDTO();
compensationDTO.setId(claim.getId());
compensationDTO.setAmount(claim.getAmount());
compensationDTO.setType(claim.getType());
compensations.add(compensationDTO);
mapToDTO(claim.getChildrenClaims());
}
return compensations;
}
I understand that the base case should return empty list but i don't know where to put the recursive function call mapToDTO(claim.getChildrenClaims());
Did you try to add compansations.addAll()?:
private List<CompensationDTO> mapToDTO(List<Claims> claims) {
List<CompensationsDTO> compensations = new ArrayList<>();
if (claims.isEmpty()) {
return new ArrayList<>();
}
for (Claim claim : claims) {
CompensationDTO compensationDTO = new CompensationDTO();
compensationDTO.setId(claim.getId());
compensationDTO.setAmount(claim.getAmount());
compensationDTO.setType(claim.getType());
compensations.add(compensationDTO);
compensations.addAll(mapToDTO(claim.getChildrenClaims()));
}
return compensations;
}
mapToDTO returns List<CompensationDTO> and you need to add these elements to your local list.
List<CompensationDTO> rec = mapToDTO(claim.getChildrenClaims());
compensations.addAll(rec);
Related
I have a list of entity. these are the response from db. I have another list of long. In the list of entity, each entity object has a filed called id. Those id will always be in ascending order.I need to traverse the entity list as per the order given through the list of long. Also I need to maintain another list of response object which will have few more fields than what we have in the entity list. I can not use transient also. The code below will give you an idea.
public List<ResponseObject> convert(List<EntityObject> entityList, List<Long> orderedIdList) {
List<ResponseObject> responseList = new ArrayList<>();
for (EntityObject object : entityList) {
ResponseObject responseObject = new ResponseObject();
responseObject.someSettermethod(object.someGettermethod());
/* other setters in responseObject which are not present in the entity object */
responseObject.otherSetters("some value");
responseList.add(responseObject);
};
return sortInOrder(responseList, orderedIdList);
}
private List<ResponseObject> sortInOrder(List<ResponseObject> responseList,List<Long> orderedIdList) {
List<ResponseObject> finalList = new ArrayList<>();
for(Long id : orderedIdList){
for(ResponseObject response : responseList){
if(response.getId().equals(id)){
finalList.add(response);
}
}
}
return finalList;
}
This is how it has been implemented for now. I would like to know if there is any better approach to enhance the performance to achieve the same output.
The sortInOrder method can be done faster than O(N^2):
Assuming, Ids are unique (let me know if its a wrong assumption):
Idea:
Create a map of Id to responseObject by iterating over the response list O(n).
Iterate over orderedIdList and check for id in map, if the id exists, add the value to response Object.
private List<ResponseObject> sortInOrder(List<ResponseObject> responseList,List<Long> orderedIdList) {
List<ResponseObject> finalList = new ArrayList<>();
Map<Long, ResponseObject> map = responseList.stream().collect(Collectors.toMap(ResponseObject::getId, respObj -> respObj));
for(Long id : orderedList) {
if(map.containsKey(id)) {
finalList.add(map.get(id));
}
}
return finalList;
}
If these lists aren't huge (like in many many thousands of entries), I wouldn't worry about performance. It's reasonable as it is and as long as you don't fail any specific performance requirements you shouldn't optimize your code for performance anyway.
You could on the other hand optimize your code for readability
by using a comparator to sort your list
by using the streams API to reduce the depth of your methods.
The comparator could be constructed using the ordering list and then comparing the indices of the ids from your resultList.
The comparator could look similar to this one:
private static class IndexComparator implements Comparator<Long> {
private final List<Long> order;
private IndexComparator(List<Long> order) {
this.order = order;
}
#Override
public int compare(Long id1, Long id2) {
return Comparator.comparingLong(order::indexOf).compare(id1, id2);
}
}
If you use map instead of a list like below, you can do it with complexity O(n) instead of O(n2)
public List<ResponseObject> convert(List<EntityObject> entityList, List<Long> orderedIdList) {
Map<Long, ResponseObject> responseMap = new HashMap<Long, ResponseObject>();
for (EntityObject object : entityList) {
ResponseObject responseObject = new ResponseObject();
responseObject.someSettermethod(object.someGettermethod());
/* other setters in responseObject which are not present in the entity object */
responseObject.otherSetters("some value");
responseMap.put(responseObject.getId(), responseObject);
};
return sortInOrder(responseMap, orderedIdList);
}
private List<ResponseObject> sortInOrder( Map<Long, ResponseObject> responseMap, List<Long> orderedIdList) {
List<ResponseObject> finalList = new ArrayList<>();
for(Long id : orderedIdList){
finalList.add(responseMap.get(id));
}
return finalList;
}
Hy, I am having trouble with comparing two list. The goal is to compare two lists, find the same values and store those values into third list. What I have found till yet is just the way to return boolean value, but no way to return list value.. any ideas?
here are my two methods for getting values from database:
#Override
public List<BrojPolice> dohvatiBrojPolice() {
List<BrojPolice> filter = jdbcTemplate.query("SELECT*FROM ins2.kalk_cpi;",new Object[]{},
(rs,rowNum) ->{
BrojPolice bp = new BrojPolice();
bp.setBroj(rs.getString("BROJ_POLICE"));
return bp;
});
return filter;
}
#Override
public List<BrojPolice> dohvatiBrojPolice2() {
List<BrojPolice> filter2 = jdbcTemplate.query("SELECT*FROM ins_RAZNO.ADND_DATOTEKA;",new Object[]{},
(rs,rowNum) ->{
BrojPolice bp = new BrojPolice();
bp.setBroj(rs.getString("BROJ_POLICE"));
return bp;
});
return filter2;
}
public List<String> brojPolice(){
boolean match = dohvatiBrojPolice().contains(dohvatiBrojPolice2());
//ideas?
return //List
}
Instead of handling this in code you could write an SQL statement that gives the desired result
SELECT
BROJ_POLICE
FROM
ins2.kalk_cpi AS a
INNER JOIN
ins_RAZNO.ADND_DATOTEKA AS b
ON
a.BROJ_POLICE = b.BROJ_POLICE
That way you waste less memory on getting 2 possibly huge lists with only some common values.
// QUERY = query from above, omitted for readability
List<BrojPolice> list = jdbcTemplate.query(QUERY, new Object[0],
(rs,rowNum) -> {
BrojPolice bp = new BrojPolice();
bp.setBroj(rs.getString("BROJ_POLICE"));
return bp;
});
How to do it in java:
List<A> a = list1();
List<A> b = list2();
// A has to implement equals and hashCode
List<A> result = new ArrayList<A>();
for (A element : a) {
if (b.contains(element)) // this requires a proper equals implementations
result.add(element);
}
return result;
Note that doing list1.contains(list2) would always be false in this case because contains checks whether the element is contained.
You can use List.retainAll as :
List<BrojPolice> common = new ArrayList<>(dohvatiBrojPolice());
common.retainAll(dohvatiBrojPolice2());
This would require the BrojPolice to be comparable with proper hashCode and equals.
If you're looking for a stream or forEach solution for this
List<BrojPolice> common = dohvatiBrojPolice().stream()
.filter(a -> dohvatiBrojPolice2().contains(a))
.collect(Collectors.toList());
First your BrojPolice class needs to have hashCode and equals method implemented so that contains method works as expected. Try below method then:
public List<BrojPolice> intersection(List< BrojPolice > list1, List<BrojPolice> list2) {
List<BrojPolice> intersection = new ArrayList<BrojPolice>();
for (BrojPolice bp : list1) {
if(list2.contains(bp)) {
list.add(bp);
}
}
return intersection;
}
I would like to split an ArrayList that I am looping trough and set a field called active which can be true or false. But at the end of loop I would like to split this collection in two groups.. active = false and active = true, so doing this I won't need to search in database twice..
for example:
private List<Classes> searchClasses(ClassItems listItems) {
List<ClassItem> items = new ArrayList<ClassItem>();
for (Iterator<ClassItem> iterator = listItems.getItems().iterator(); iterator.hasNext();) {
ClassItems item = iterator.next();
ClassEntityManager classEnt = ClassEntityManager.search(item.getId);
if(classEnt.active()){
item.setActive(true);
items.add(item);
}
}
return items;
}
What is the best approach to do this??
Make two lists instead of one.
if(classEnt.active()) {
activeItems.add(item);
item.setActive(true);
} else {
inactiveItems.add(item);
}
Use two collections, one for actives and the other for not actives.
When you fetch the data from the DB, simply put the CalssItem in the correct list:
private List<ClassItem> searchClasses(ClassItems listItems) {
List<ClassItem> activeItems= new ArrayList<ClassItem>();
List<ClassItem> notActiveItems= new ArrayList<ClassItem>();
Iterator<ClassItem> i = listItems.getItems().iterator();
while(i.hasNext()) { //This is a better approach.
ClassEntityManager classEnt = ClassEntityManager.search(i.next().getId);
if(classEnt.active()){
item.setActive(true);
activeItems.add(item);
}else{
item.setActive(false);
notActiveItems.add(item);
}
}
List<ClassItem> ret = new ArrayList<ClassItem>(activeItems);
ret.addAll(notActiveItems);
return ret;
}
BUT, in this way, both activeItems and notActiveItems are unreacheable. Best thing to do is to have a loop outside your method that checks if the ClassItem is active or not. In this way both activeItems and notActiveItems can be deleted from the method:
private List<ClassItem> searchClasses(ClassItems listItems) {
List<ClassItem> items= new ArrayList<ClassItem>();
Iterator<ClassItem> i = listItems.getItems().iterator();
while(i.hasNext()) { //This is a better approach.
ClassEntityManager classEnt = ClassEntityManager.search(i.next().getId);
item.setActive(classEnt.active());
items.add(item);
}
return items;
}
And to use the list:
List<ClassItem> items = searchClasses(classItems);
for(ClassItem item: items){
if(item.isActive()){
//do something
}else{
//do something else
}
}
Better yet is to use the magnificient and beautiful Java 8 Stream API:
List<ClassItem> active = items.stream().filter(x->x.isActive).collect(Collectors.toList());
List<ClassItem> notActive = items.stream().filter(x->!x.isActive).collect(Collectors.toList());
or the one liner:
List<ClassItem> active = searchClasses(classItems).stream().filter(x->x.isActive).collect(Collectors.toList());
NOTES:
Your code has a return type of List<Classes>, while the returned value is of List<ClassItem>. Which is right?
Your iterator has a generic type of ClassItem while the next() method returns a ClassItems object. Which is right?
I have following code. In the first i tried to set values in the list called 'unavailable'.
Next, in the for each I have to produce a cycle on the list domainStr minus unavailable. How can i do it?
public Result execute(List<String> domainsStr) {
Result result = new Result();
try {
List<String> domains = domainService.findByNames(domainsStr);
result.setUnavailable(domains);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
for (String domain : domainsStr) {
......
}
return result;
}
public static class Result {
private List<String> unavailable = new ArrayList<>();
public List<String> getUnavailable() {
return unavailable;
}
public void setUnavailable(List<String> unavailable) {
this.unavailable = unavailable;
}
}
removeAll(Collection c) is the function which would be the most helpful to you. Having said that, this will work properly only if you have the equals method correctly defined for your Domain object. In this case it is a String so it doesnt matter. But, just to keep it in mind.
so just say, domainsStr.removeAll(result.getUnavailable());
Also, if the Result class is static, why the new object creation here?
Result result = new Result();
This result.setUnavailable(domains);
can be changed to
Result.setUnavailable(domains);
I have to to produce a cycle on the list domainStr minus unavailable.
If I understood correctly, I think you are looking for the removeAll method :
Removes from this list all of its elements that are contained in the
specified collection (optional operation).
domainsStr.removeAll(result.getUnavailable());
for (String domain : domainsStr) {
}
If you want to let domainsStr unchanged, you can create a temporary list and perfom these operations on it.
List<String> tempList = new ArrayList<String>(domainsStr);
tempList.removeAll(result.getUnavailable());
for(String domain : tempList){
.....
I put them into a tempt list so you don't lose the items in the domainsStr list.
I have an object as Riziv with three variables as id, cnk and product. Then I search in a databank for this object and add it to a ArrayList as ArrayList<Riziv> list.
Now I should checkout if all object in his array are the same cnk then return true otherwise I should return all objects which are not the same cnk with error message.
public class Riziv{ String id, cnk, product; }
ArrayList<Riziv> list = getArrayListFromDatabank(id);
public void getDuplicatedWhichHasTheSameCnk(){
}
}
Using standard JVM structures (MultiMap is provided by guava), you can do that:
public List<Riviz> getDuplicates(final List<Riviz> l)
{
final HashMap<String, List<Riviz>> m = new HashMap<String, List<Riviz>>();
final List<Riviz> ret = new ArrayList<Riviz>();
String cnk;
for (final Riviz r: l) {
cnk = r.getCnk();
if (!m.contains(cnk))
m.add(cnk, new ArrayList<Riviz>());
m.get(cnk).add(r);
}
List<Riviz> tmp;
for (final Map.Entry<String, List<Riviz>> entry: m.entrySet()) {
tmp = entry.getValue();
if (tmp.size() == 1) // no dups
continue;
ret.addAll(tmp);
}
return ret;
}
ret will contain the duplicates. You can change that function to return a Map<String, Riviz> instead, and filter out entries where the list size is only one. You'll then get a map with the conflicting cnks as keys and a list of dups as values.
I am not clear exactly what you want however I suspect you want something like this.
MultiMap<Key, Riziv> multiMap =
List<Riziv> list =
for(Riziv r: list)
multiMap.put(r.getCnk(), r);
for(Key cnk: multiMap.keySet()) {
Collection<Riziv> sameCnk = multiMap.get(cnk);
// check size and compare entries
}
The multi-map will have the list of Riziv objects for each Cnk.
One way to do it is write a comparator to sort the list by cnk String and then compare each consecutive cnk String to the next, if you find a duplicate, they will be right next to eachother.
1.) Sort the list using a comparator by sorting on the cnk variable.
2.) Compare each element in the list to the next for duplicates.
There's probably many other ways to solve this, this is just the first that came to mind.
I did not test this so you have been forewarned lol:
ArrayList<Riziv> rizArray = new ArrayList<Riziv>();
//Sort the array by the CNK variable.
Collections.sort(rizArray, new Comparator<Riziv>(){
#Override
public int compare(Riziv arg0, Riziv arg1) {
//Return the comparison of the Strings.
//Use .compareToIgnoreCase if you want to ignore upper/lower case.
return arg0.getCnk().compareTo(arg1.getCnk());
}
});
//List should be in alphabetical order at this point.
List<Riziv> duplicates = new ArrayList<Riziv>();
Riziv rizPrevious = null;
for(Riziv riz: rizArray){
if(rizPrevious == null){
rizPrevious = riz;
continue;
}
if(riz.getCnk().compareTo(rizPrevious.getCnk()) == 0){
duplicates.add(riz);
}
rizPrevious = riz;
}