I want to iterate a list in a specify order using the Interface Iterator.
In this case, I want to iterate the list (listofproducts) in descending product.prize order.
public class Invoice {
private static int static_id;
private int id;
private String date;
private List<Product> listofproduct = new ArrayList<Product>();
private boolean open;
}
public class Product {
private static int count = 0;
private int code;
private String name;
private String description;
private double price;
}
I have a public method to get the price.
How can I solve this?
If the amount of data isn't too big you can do the following without thinking about the performace:
List<Product> sortList = new ArrayList<>(origList);
Collections.sort(sortList, new Comparator<Product>() {
#Override
public int compare(Product arg0, Product arg1) {
return (int)(arg1.getPrice() - arg0.getPrice());
}
});
This will create a copy of the original list which will be sorted by a comparator. After that, iterating over sortList will be sorted by price (descending)
You should use the Comparable<T> interface to implement your comparaison logic :
class Product implements Comparable<Product>{
private static int count = 0;
private int code;
private String name;
private String description;
private Double price;
#Override
public int compareTo(Product p) {
return price.compareTo(p.getPrice());
}
}
Now to sort the list you can simply use :
Collections.sort(listOfProduct);
There are two way to achieve that. With Comparator it is easy to use, you should create a new implementation of the interface Comparator and then implement the compare and equals methods. It is really powerful because you can create several comparator to sort in different fields.
You can also make you Product as Comparable and then implements the compareTo method.
You can see sample with camparator and comparable interfaces
Related
I am working in Java and I want to make a deep copy of a MoleculeDTO object. I tried to make a copy constructor too, but it is not working and it is refering to the initial object.
public class MoleculeDTO {
private int ID;
private String name;
private List<AtomDTO> atoms = new ArrayList<>();
private int nrAtoms =0;
public MoleculeDTO(String name, List<AtomDTO> atoms, int nrAtoms) {
this.name = name;
this.atoms = atoms;
this.nrAtoms = nrAtoms;
}
public MoleculeDTO(MoleculeDTO molecule) {
this(molecule.getName(), molecule.getAtoms(), molecule.getNrAtoms());
}
...getter, setter
}
Here is class AtomDTO.
public class AtomDTO{
private int ID;
private String name;
private String symbol;
private int nrOfBonds;
private List<BondDTO> bonds = new ArrayList<>();
private int type;
private AnchorNode anchorNode;
public AtomDTO(String name, String symbol, int nrOfBonds, List<BondDTO> bonds, int type) {
this.name = name;
this.nrOfBonds = nrOfBonds;
this.bonds = bonds;
this.type = type;
}
public AtomDTO(AtomDTO copyAtom) {
this(copyAtom.getName(),copyAtom.getSymbol(), copyAtom.getNrOfBonds(), copyAtom.getBonds(), copyAtom.getType());
}
...getter, setter
}
Here is class BondDTO.
public class BondDTO {
private int ID;
private int otherAtomID;
private int otherAtomType;
private int bondType;
public BondDTO(int otherAtomID, int otherAtomType, int bondType) {
this.otherAtomID = otherAtomID;
this.otherAtomType = otherAtomType;
this.bondType = bondType;
}
public BondDTO(BondDTO copyBond) {
this(copyBond.getOtherAtomID(), copyBond.otherAtomType, copyBond.bondType);
}
...getter, setter
}
Your copy constructors are just doing shallow copies of each field. That's fine for strings because they're immutable, and it's fine for ints because they're primitive (which means they lack identity and are immutable). In those cases, there is no important difference between shallow and deep copies. But it doesn't work in general for lists because lists can be mutable and so can their elements. So instead of just pointing at the same list, you need to make a new list and deep copy each element of the original list into the new one.
Use this helper method to make deep copies of any lists:
static <T> List<T> deepCopyList(List<T> list, UnaryOperator<T> deepCopyElement) {
return list.stream().map(deepCopyElement).collect(
Collectors.toCollection(ArrayList::new)
);
}
Like so:
public AtomDTO(AtomDTO that) {
this(that.getName(), that.getType(), deepCopyList(that.getBonds(), BondDTO::new));
}
I´m having troubles to define a method that sort a list of the same class where is defined this method.
For example the class is defined with the following attributes:
public abstract class Licence {
//other attributes
protected List<People> myList;
//Constructor and other methods
//The method I want
public List<People> getPeopleInOrder ( Comparator c)
List<People> aux = new ArrayList<People>(this.myList);
Collections.sort(aux, c);
return aux;
And also I have this class
class CompPeople implements Comparator<People>{
public int compare( People e1, People e2) {
// Declaration the criteria of comparison
if ( c1 == 0) {
if (c2 == 0 ) return c3;
else return c2;
}
else return c1;
}
}
But when I call in main method
List<People> myNewList = Mylicence.getPeopleInOrder(new CompPeople());
EDIT: Before I was trying to sort a unmodifiable list, I changed it and now it gives me empty list.
I know I can use the method sort of Collections but what I want is a method of class Licence that sort its list with a given comparator. Thanks in advance
I think you have incorrect comparator.
Let define a People class:
public class People {
private String name;
private String city;
}
In case you plan to use different ways to compare these object, then it is better to use custom comparators. E.g. this is two comparators that sort people by one of the field. I recommend to define different comparators as part of People class:
public class People {
private String name;
private String city;
public static final Comparator<People> SORT_BY_NAME_ASC = (one, two) -> one.name.compareToIgnoreCase(two.name);
public static final Comparator<People> SORT_BY_CITY_ASC = (one, two) -> one.city.compareToIgnoreCase(two.city);
}
Now you can use it sort List<People> peoples:
people.sort(People.SORT_BY_NAME_ASC); // sort by name asc
people.sort(People.SORT_BY_CITY_ASC); // sort by city asc
people.sort(People.SORT_BY_NAME_ASC.thenComparing(People.SORT_BY_CITY_ASC)); // sort by name and city asc
You method getPeopleInOrder() could look like this:
public List<People> getPeopleInOrder(Comparator<People> comparator) {
if(myList.isEmpty())
return Collections.emptyList();
List<People> aux = new ArrayList<>(myList);
aux.sort(comparator);
return aux;
}
...or using Streams like this:
public List<People> getPeopleInOrder(Comparator<People> comparator) {
return myList.stream().sorted(comparator).collect(Collectors.toList());
}
In case you want only one comparator, then you have two ways.
class People implements Comparable
class People implements Comparable<People> {
private String name;
private String city;
#Override
public int compareTo(People people) {
int res = name.compareToIgnoreCase(people.name);
res = res == 0 ? city.compareToIgnoreCase(people.city) : res;
// compare other fields you want
return res;
}
}
Use single Comparator
public class People {
private String name;
private String city;
public static final Comparator<People> SORTY_BY_NAME_AND_CITY = (one, two) -> {
int res = one.name.compareToIgnoreCase(two.name);
res = res == 0 ? one.city.compareToIgnoreCase(two.city) : res;
// compare other fields you want
return res;
};
}
As you should be able to guess from the comment, the problem is the unmodifiableList(). For a copy, just create a new List.
public List<People> getPeopleInOrder ( Comparator c)
List<People> aux = new ArrayList<>(this.myList);
Collections.sort(aux, c);
return aux;
}
With this class:
public class MyClass implements Comparable<MyClass> {
private String status;
private String name;
private String firstName;
#Override
public int compareTo(MyClass o) {
return 0;
}
}
I'd like to sort a list of MyClass objects with this order:
Firstly, status = "open", then "working" then, "close"
Secondly, name = "toto", then "titi"
Finally, firstName = "tutu", "tata"
How can I do this with the Comparable interface ?
I would do this like so: first define a set of lists which define the order for each field:
private static List<String> statusOrder = Arrays.asList("open", "working", "close");
private static List<String> nameOrder = Arrays.asList("toto", "titi");
private static List<String> firstNameOrder = Arrays.asList("tutu", "tata");
Then use List.indexOf to get the position of the element in the list, and then simply subtract the results:
#Override
public int compareTo(MyClass o) {
final int statusComp = statusOrder.indexOf(status) - statusOrder.indexOf(o.status);
if (statusComp != 0) return statusComp;
final int nameComp = nameOrder.indexOf(name) - nameOrder.indexOf(o.name);
if (nameComp != 0) return nameComp;
return firstNameOrder.indexOf(firstName) - firstNameOrder.indexOf(o.firstName);
}
The issue with this approach is that indexOf will return -1 if the element is not in the list. You would need to define the behaviour in the case where MyClass contains non-standard values (perhaps it will never happen).
I have a Set<MultiAdminComponent> rootItems = new HashSet<>();HashSet.
In this I have all my Screen.
In my HashSet I am going to have all my rows. I want to sort the MultiAdminComponent based on rowId.
This is MultiAdminComponent
public class MultiAdminComponent {
private String componentName;
private String componentIdentification;
private String componentType;
private String componentState;
private String componentUrl;
private String componentId;
private String rowId;
private List<MultiAdminComponent> items;
private int componentStateId;
private int ctastatus;
private String actionId;
private String actionToPerform;
private int orderNumber;
private int ctarevision;
How can I sort based on RowId in MultiAdminComponent bean
Since you are on Java 8, you can leverage Stream API and Comparator.comparing() for this:
List<MultiAdminComponent> sortedList = rootItems.stream()
.sorted(Comparator.comparing(MultiAdminComponent::getRowId))
.collect(Collectors.toList()); // collect to whatever you want
Keep in mind that HashSet does not maintain order so you should keep the sorted result in some other data structure.
And remember that this is not going to sort your Set this is going to return a List of naturally sorted MultiAdminComponents and you need to capture the result of this operation.
Just to let you know, there are few more Sets.
HashSet is not ordered/sorted
LinkedHashSet sorted by the order that it's been inserted
TreeSet sorted in natural order
I know the question been answered, but truly I can't see a point of using a HashSet which is not ordered and then try to order it when you can just use a TreeSet?
Before Java 1.8 version, which can help you
public class Test {
public static void main(String[] args) {
MultiAdminComponent m1 = new MultiAdminComponent("1");
MultiAdminComponent m2 = new MultiAdminComponent("2");
MultiAdminComponent m3 = new MultiAdminComponent("3");
Set<MultiAdminComponent> set = new HashSet<MultiAdminComponent>();
set.add(m1);
set.add(m3);
set.add(m2);
List<MultiAdminComponent> list = new ArrayList<MultiAdminComponent>(set);
for (MultiAdminComponent m : list) {
System.out.println("before" + m.getRowId());
}
Collections.sort(list, new Comparator<MultiAdminComponent>() {
#Override
public int compare(MultiAdminComponent m1, MultiAdminComponent m2) {
return m1.getRowId().compareTo(m2.getRowId());
}
});
for (MultiAdminComponent m : list) {
System.out.println("after" + m.getRowId());
}
}
}
class MultiAdminComponent {
private String rowId;
public MultiAdminComponent(String rowId) {
super();
this.rowId = rowId;
}
public String getRowId() {
return rowId;
}
public void setRowId(String rowId) {
this.rowId = rowId;
}
}
I have a list of java object that have 4 members.
int id;
String name;
String age;
int order;
I want to sort the list of this object w.r.t order.
class Foo {
private int id;
private String name;
private String age;
private int order;
//accessors
}
Use Custom Comparator
List<Foo> list = null;
Collections.sort(list, new Comparator<Foo>() {
public int compare(Foo o1, Foo o2) {
return Integer.valueOf(o1.getOrder()).compareTo(Integer.valueOf( o2.getOrder()));
}
});
You can Implement java.lang.Comparable interface and put the sorting logic in compareTo(T o) or else
you can have custom java.lang.Comparator and have the logic in compare() method.
I would suggest to implement custom Comparator, as later if you try to modify your sorting criteria, ll be easily done.
Make the object implement Comparable.
public class Person implements Comparable<Person> {
private int id;
private String name;
private int order;
public int compareTo(Person p) {
return p.order - this.order;
}
}
You can then use objects of this class Person in any sorted list such as PriorityQueue or you could simply use Collections.sort(personList) for that.
Use a PriorityQueue and let your objects extend Comparable.
You also have to implement the compareTo(object o) method.