How to apply range criteria for List of Objects? - java

I have one Object say
class ABC{
private String name;
private String code;
private BigDecimal priceM;
private BigDecimal priceL;
private BigDecimal priceO;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public BigDecimal getPriceM() {
return priceM;
}
public void setPriceM(BigDecimal priceM) {
this.priceM = priceM;
}
public BigDecimal getPriceL() {
return priceL;
}
public void setPriceL(BigDecimal priceL) {
this.priceL = priceL;
}
public BigDecimal getPriceO() {
return priceO;
}
public void setPriceO(BigDecimal priceO) {
this.priceO = priceO;
}
}
Now, say i have a list of ABC and at some point i want that list to filter according to searchCriteria.
Is there any efficient way to achieve this...???
Example ,
I have
AIM :
List and i want new List which will contain List of ABC with priceM values between 100 to 200

Google Guava have some classes around Matchers and Predicate maybe that can help
http://java.dzone.com/articles/google-guava-goodness-matching
Maybe you can use reflection to achieve automatic matching

The new APIs in JDK 8
List<ABC> items = asList(...);
Stream<ABC> stream = items.stream();
stream.filter( item -> item.getPrice() >= 100 && item.getPrice() <= 200 )
.forEach ( System.out::println );

Java provide a Collection.sort(list, comp) method which takes a list and Comparator object as argument
In that case pass your original list which need to be sort and create a Comparator object and override the compare method which is rules for sorting.
You can create multiple Comparator object based on your requirement.
Please refer below link for more help.
http://www.vogella.com/blog/2009/08/04/collections-sort-java/
How do I sort a list by different parameters at different timed

Related

Is it bad practice to return Enums in Java?

Lets say I have a class to model an item in a game like so:
public class Item {
private final EnumItem type;
public Item(EnumItem type) {
this.type = type;
}
public Item(String name) {
this.type = EnumItem.fromName(name);
}
}
public enum EnumItem {
MACHINE_GUN("machine_gun"),
SWORD("sword"),
BAT("bat"),
DEFAULT("default");
private final String name;
public EnumItem(name) {
this.name = name;
}
public String getName() { return name; }
public static EnumItem fromName(String name) {
for(EnumItem i: EnumItem.values()) {
if(i.name.equals(name)) {
return i;
} else {
return EnumItem.DEFAULT;
}
}
}
}
Assume that .equals() and .hashCode() of Item are overridden correctly to compare the internal Enum.
Now I want a way to distinguish these items with a getter in Item: should I return an Enum or the String name? Is it good practice to return an Enum in general? Or is there a better way to distinguish these Items? Because returning the enum kind of looks like exposing the rep to me and I don't want my colleagues to use EnumItem directly to compare Items.
The approaches I thought of are the following:
string getName() to do something like item1.getName().equals("machine_gun");
EnumItem getEnum() to do item1.getEnum().equals(EnumItem.MACHINE_GUN);
item1.equals(new Item("machine_gun"));
static name(String name) { new Item(name) } to do item1.equals(Item.name("machine_gun"));
I don't know what should I do, I'd appreciate some insight from experienced programmers.
I know they look like they would from context, but in my use case these items have no special functionality that would justify extending from the base Item class.
Is this good practice? Sure, you're using aggregation since Item doesn't depend on EnumItem, which is fine. That being said, could it be done better? Sure. Is the alternative I provide the only solution? No.
Alternative
If you want this to be extensible, consider using an interface to represent an item. Then allow the interface to extend this interface to provide some standard types. Alternatively you could use composition or aggregation to define a type inside EnumItem that implements the Item interface to ensure that equals/hashcode for the Item are always override and adhere to some contract.
interface Item {
String key();
}
enum EnumItem implement Item {
private final String key;
EnumItem(String key) {
this.key = key;
}
#Override
public String key() {
return key;
}
}
class AbstractItem implements Item {
// constructor, override name()
}
Item item = EnumItem.FOO_BAR;
Item item2 = new AbstractItem("FooBar");
Item item3 = () -> "FooBar";

Class method that sort a list of objects with a comparator given as parameter (Java)

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;
}

Sorting ArrayList Hashmap

I have an ArrayList<HashMap<String,String>> and I want to sort it. My ArrayList output in Logcat is like this:
[{num=0, username=p, startPoliPro=A, finalPoliPro=B, diff=0},
{num=1, username=e, startPoliPro=C, finalPoliPro=D, diff=548.0Km},
{num=2, username=e, startPoliPro=E, finalPoliPro=F, diff=3.0Km}]
I want to sort the list based on "diff" value by ascending order so that Logcat has to be like:
[{num=0, username=p, startPoliPro=A, finalPoliPro=B, diff=0},
{num=2, username=e, startPoliPro=E, finalPoliPro=F, diff=3.0Km},
{num=1, username=e, startPoliPro=C, finalPoliPro=D, diff=548.0Km}]
I have read many similar topics and tried something like
Collections.sort(final_itinList, new Comparator<HashMap< String,String >>() {
#Override
public int compare(HashMap<String, String> lhs, HashMap<String, String> rhs) {
// Do your comparison logic here and retrn accordingly.
return lhs.get("diff").compareTo(rhs.get("diff"));
}
});
with no success. Any help would be appreciated
Currently, you are trying to compare two String Objects:
return lhs.get("diff").compareTo(rhs.get("diff"));
What you really want to do is comparing the returned Integers, so you would need to do something like this:
return (Integer.parseInt(lhs.get("diff")) - Integer.parseInt(rhs.get("diff")));
Your Comparator is comparing two Strings. That's probably why the list is not sorted correctly. The "diff" string should be parsed as an integer (or float) to compare it.
If your objects always have the same structure, I would advise to create a List of a custom object (where the diff is an integer representing the number of kilometers) instead of using a List of Maps. In that case, you could make your custom object implement Comparable.
Something like :
public class MyCustomObject implements Comparable<MyCustomObject> {
private String mNum;
private String mUsername;
private String mStartPoliPro;
private String mFinalPoliPro;
private int mDiff;
#Override
public int compareTo(MyCustomObject another) {
return mDiff - another.getDiff();
}
public String getNum() {
return mNum;
}
public void setNum(String num) {
mNum = num;
}
public String getUsername() {
return mUsername;
}
public void setUsername(String username) {
mUsername = username;
}
public String getStartPoliPro() {
return mStartPoliPro;
}
public void setStartPoliPro(String startPoliPro) {
mStartPoliPro = startPoliPro;
}
public String getFinalPoliPro() {
return mFinalPoliPro;
}
public void setFinalPoliPro(String finalPoliPro) {
mFinalPoliPro = finalPoliPro;
}
public int getDiff() {
return mDiff;
}
public void setDiff(int diff) {
mDiff = diff;
}
}
and then simply call
List<MyCustomObject> myList = // create your object list
Collections.sort(myList);

About sorting array list

I am trying to ensure that the objects i insert in productDatabase have not been already inserted and that i sort my arraylist using method sortData but without using any comparators in method sortData
public class Application {
public static void main(String[] args) {
Product p = new Product(15,"test",3.45);
Product p2 = new Product(15,"test",3.45);
Product p3 = new Product(4716,"koukouroukou",1.25);
Product p4 = new Product(6002,"bananofatsoula",0.60);
ProductDatabase productDatabase = new ProductDatabase();
productDatabase.addProduct(p);
productDatabase.addProduct(p2);
productDatabase.addProduct(p3);
productDatabase.addProduct(p4);
productDatabase.printDatabase();
productDatabase.sortDatabase();
productDatabase.printDatabase();
}
public class Product {
private int code;
private String name;
private double price;
public Product(int code, String name, double price){
this.code = code;
this.name = name;
this.price = price;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String toString(){
return code+" , description: "+name+", price: "+price;
}
public int hashCode(){
return 31 * code + name.hashCode();
}
public boolean equals(Object o){
Product other = (Product)o;
if (this.code == other.code){
return true;
}
else{
return false;
}
}
import java.util.ArrayList;
import java.util.Collection;
public class ProductDatabase {
private ArrayList<Product> productDatabase;
public ProductDatabase(){
productDatabase = new ArrayList<Product>();
}
public void addProduct(Product p){
if(!productDatabase.contains(p)){
productDatabase.add(p);
}
}
public void printDatabase(){
for(Product product : productDatabase){
System.out.println(product);
}
}
public void sortDatabase(){
// ????????????????????????????????????????????????????????????
So my questions are
Does contain(p) is enough to ensure that the same product is not already in the list?
products are the same when they have the same code and name.if not what i have to do?
How i sort my withous using comparators in class ProductDatabase.maybe by a new method in product ?
Does productDatabase extends Product???
You can return bool value in order to know the product is already there or not . Code is used to ensure the differentiation of products if not add another code id.
Product instance will carry information of just one Product so Sort must be done in the member function of class having all the records of product, not just one.
No product_database does not extend product . It is a log of product class not a part .
your questions 1 and 2 are a little unclear. Can you re-write them? As for question 3. No ProductDatabase does not extend product, neither should it. ProductDatabase HAS products. ProductDatabase is not a product
Yes, contains() is enough (in our case) to ensure uniqueness
Since you implemented equals and hashCode - you're good
You don't need to sort if you don't have another purpose to do so, but since you're using an ArrayList every time contains() is called it iterates the whole list which is not very efficient. A better implementation would use Set (a HashSet for example)
ProductDatabase does not have to extend Product - it contains a list/set of products but it doesn't have any character/behavior like Product
Yes, contain(p) is enough to ensure that the same product is not already in the list, because you overrided "equals" method.
In "equals" you can use shorter construction:
Product other = (Product)o;
return this.code == other.code;
For sort ArrayList with java.util.Collections class two options possible:
Collections.sort(List list, Comparator c). You have to write own Comparator class and pass as second parameter.
Collections.sort(List list) and class Product must implement Comparable interface
Yes, Contain(p) is enough to ensure that the same product is not already in the list BUT that is NOT efficient. Use a Set instead of ArrayList.
For question 2, you have to decide the when the two products are equal and code that in your equals method like you did for 'product code'

How to call a method from another class in Java

So, I have this class:
public class Product {
private String name, id, info ;
private int quantity;
public Product(String newName, String newID, String newInfo, Integer newQuantity){
setName(newName);
setID(newID);
setPrice(newInfo);
setQuantity(newQuantity);}
public void setName(String name) {
this.name = name; }
public void setID(String id) {
this.id = id; }
public void setPrice(String info) {
this.info = info; }
public void setQuantity(Integer quantity) {
this.quantity = quantity; }
public String getID( ) {
return id; }
public String getName( ) {
return name; }
public String getInfo( ) {
return info; }
public int getQuantity( ) {
return quantity; }
In another class i have this:
public class Invoice implements Group<Product> {
private HashMap<String, Product> prod = new HashMap<String, Product>( );
public Invoice(){ }
public void addProd(Product a) {
prod.put(??getID()??,new Product(??));
}
}
If this data was user generated rather than me, I would use the getID() method right?
So in my class invoice, how do i use the method getID(), so that I can use it in the parameter for my key value in the HashMap? Also is there a way to add 3 values (name info quan) to the hashmap without making a new class?
I see that you get Product object with ref "a" as parameter to your addProd method.
And you can get id by just using a.getID(). It should look as:
public void addProd(Product a) {
prod.put(a.getID(),a);
}
I didn't understand second part of your question.. I think you already have 3 values in your Product object and you put Product object to Map, So why do you require another way ?
Your class Product does not compile, because you have the name Item in your constructor. The constructor name must match the class name. So change that to Product. The same applies to Invoice vs ShoppingCart. Constructor and Class names must match.
As per your comment, you'd like to add four product values to a Map. The key being one of the values of the product itself. Try this:
Product p = new Product(name, id, info, quantity);
cart.addProd(p);
...
public void addProd(Product p) {
prod.put(p.getId(), p);
}
Maps can only map a single value to a single key, so you must have some sort of container for the values you wish to collate into one value. This can be an object (Product) or you could use a collection (e.g. List). I strongly recommend the former.
For your question about putting 3 values in your map, I don't think there's a way for you to put 3 values into one key without creating a class. An alternative is to store a Map<String, List<String>> assuming your 3 values are type String, or, Map<String, Map<String, String>>.

Categories

Resources