Java Comparator for Objects with multiple fields [closed] - java

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I have an Object Collection with 5 fields:
id;
entityType;
entityId;
brandId;
productId;
To sort an ArrayList of Collection I have written the following Comparaor.
Comparator<Collection> collectionComparator = new Comparator<Collection>() {
#Override
public int compare(Collection collection1, Collection collection2) {
if(collection1.getId().equals(collection2.getId())) {
if(collection1.getEntityType().equals(collection2.getEntityType())) {
if(collection1.getEntityId().equals(collection2.getEntityId())) {
if(collection1.getBrandId().equals(collection2.getBrandId())) {
return collection1.getProductId().compareTo(collection2.getProductId());
} else {
return collection1.getBrandId().compareTo(collection2.getBrandId());
}
} else {
return collection1.getEntityId().compareTo(collection2.getEntityId());
}
} else {
return collection1.getEntityType().compareTo(collection2.getEntityType());
}
}
return collection1.getId().compareTo(collection2.getId());
}
};
Is this the right way to implement Comparator on the object which has multiple fields to compare?

Your method might be correct, but it is inefficient (unnecessarily calls equals) and difficult to read. It could be rewritten something like this:
public int compare(Collection c1, Collection c2)
{
int n;
n = c1.id.compareTo(c2.id);
if (n != 0) return n;
n = c1.entityType.compareTo(c2.entityType);
if (n != 0) return n;
n = c1.brandId.compareTo(c2.brandId);
if (n != 0) return n;
return c1.productId.compareTo(c2.productId);
}
Even better is to use a library method which abstracts all this logic away so you don't have to think about it. E.g. using apache.commons.lang CompareToBuilder
public int compare(Collection c1, Collection c2)
{
return new CompareToBuilder()
.append(c1.id, c2.id)
.append(c1.entityType, c2.entityType)
.append(c1.brandId, c2.brandId)
.append(c1.productId, c2.productId)
.toComparison();
}

First, Collection is a class from java.util package, so it's probably not the best idea to name your own class Collection too, although it is certainly possible.
Second, JDK8 have some neat ways to create comparators, check here: jdk8 comparators
Esspecially section 6 and 9.
EDIT: Without JKD8:
When comparing by 5 different attributes, I wouldn't hardcode the comparasion like that, you can always create your own comparator chainer (something like point 9 from previous link) and chain 5 separate comparators together.

Related

How to create a class of two integers (a sort of custom type) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 months ago.
Improve this question
Basically need to create a class which is custom type that has two integers: -1 and 1, instead of all the integers that exist.
If you would suggest using enum (never implemented before), could you please suggest how would that work.
public class PlusOrMinusOne{
private int plusOne=1;
private int minusOne=-1;
}
Java does not let you write your own primitives, and does not have operator overloading. It is therefore simply impossible to have a class such that any expressions that are of that type act like a number. In other words, given:
PlusOrMinusOne a = ...;
int b = a + 1; // cannot be made to work
if (a == -1) // cannot be made to work
What you can do is simply create 2 instances such that they are the only instances of a given class. One of them is the value associated with +1, the other with -1. There is nothing specific about these 2 instances that reflects that they represent -1 or +1 - you can code them however you like.
enum is the general way to do this - it takes care of ensuring nobody can make instances other than the ones you defined, for example.
public enum PlusOrMinusOne /* horrible name, come up with a better one */ {
PLUS_ONE(+1),
MINUS_ONE(-1),
;
private final int value;
PlusOrMinusOne(int value) {
this.value = value;
}
public static PlusOrMinusOne of(int value) {
if (value == -1) return MINUS_ONE;
if (value == +1) return PLUS_ONE;
throw new IllegalArgumentException("" + value);
}
public int getValue() {
return value;
}
public PlusOrMinusOne neg() {
if (this == PLUS_ONE) return MINUS_ONE;
return PLUS_ONE;
}
public String toString() {
return this == PLUS_ONE ? "+1" : "-1";
}
}
When using enums you can define custom fields, so in your case you can do for example:
public enum CustomNumber {
PLUS_ONE(1),
MINUS_ONE(-1);
public final int value;
CustomNumber(int value) {
this.value = value;
}
}
public static void main(String[] args) {
System.out.println(CustomNumber.MINUS_ONE.value);
System.out.println(CustomNumber.PLUS_ONE.value);
}
enum PlusOrMinusOne {
PLUS_ONE(1),
MINUS_ONE(-1);
public final int num;
PlusOrMinusOne(int num) {
this.num = num;
}
}
public static void main(String[] args) {
System.out.println(CustomNumber.MINUS_ONE.num);
System.out.println(CustomNumber.PLUS_ONE.num);
}

What is the better approach for recursive function returning boolean values [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
I was practicing linked-list problem: search element using recursion in Java and was just curious to know which approach is better?
A:
protected boolean searchElement(Node current, int element){
boolean res = false;
if(current != null){
if(current.getData() == elem) res = true;
else function(current.getNext(),elem);
}
else res = false;
return res;
}
B:
protected boolean searchElement(Node current, int elem){
if(current != null){
if(current.getData() == elem) return true;
else search(current.getNext(), elem);
}
return false;
}
Unless there's specific Java-hackish bytecode injection optimization reasons for using end-recursion/tail-call strategy in recursive functions, I would even go for this (fail-fast-fail-early):
protected boolean function(arguments){
if(!condition_1) return false;
if(condition_2) return true;
return function(arguments);
}
BTW you may have an error in your pseudo code:
In both A and B, the handling of
else function(arguments);
looks inconsequential. It will run the function, but both implementations will return false, no matter what function() does (unless it throws an uncaught exception/throwable). This indicates either
a mistake in programming,
or some side-effects (changing exterior state variables such as static or member variables), which recursive functions rather should NOT do
If this is only a mistake in programming/design, I suggest you always translate pseudocode into real code. This way the compiler will usually tell you such things, make them more evident. Amp up your clean code / code smell warning settings.
Oh, and another note to consider: you can always replace recursive functions with a loop and some variables/lists, which usually drastically increases speed (no creation and release of stack frames when running) but often reduces readability (multiple variables to mess up, instead of cleanly assigned parameters).
For your example, as the impact of the call to function() is unclear, I cannot present you a meaningful example here.
I prefer handling the special cases first, then the recursion (as far as feasible).
This in a code style with several returns - which many do not find good style.
But it prevents nested conditions and else.
protected boolean searchElement(Node current, int element) {
if (current == null) {
return false;
}
if (current.getData() == elem) {
return true;
}
return search(current.getNext(), elem);
}
Case: terminating condition on null node.
Case: found.
Recursion, here last, so called tail recursion.
Tail recursion can be easily transformed to iteration.
protected boolean searchElement(Node current, int element) {
while (current != null) {
if (current.getData() == elem) {
return true;
}
current = current.getNext();
}
return false;
}

Get index of an arraylist using property of an contained object in java [duplicate]

This question already has answers here:
Searching in a ArrayList with custom objects for certain strings
(9 answers)
Closed 9 years ago.
I'm having an list of Object type. In that I have one String property idNum. Now I want to get the index of the object in the list by passing the idNum.
List<Object1> objList=new ArrayList<Object1>();
I don't know how to give objList.indexOf(// Don't know how to give here);
Is it possible to do this without iterating the list. I want to use indexOf() method only.
Write a small helper method.
private int getIndexByProperty(String yourString) {
for (int i = 0; i < objList.size(); i++) {
if (object1 !=null && object1.getIdNum().equals(yourString)) {
return i;
}
}
return -1;// not there is list
}
Do not forget to return -1 if not found.
Implement equals (and hashCode) in Object1 class based on idNum field, then you use List.indexOf like this
int i = objList.indexOf(new Object(idNum));
or make a special class for seaching
final String idNum = "1";
int i = list.indexOf(new Object() {
public boolean equals(Object obj) {
return ((X)obj).idNum.equals(idNum);
}
});
You cannot do this with indexOf. Instead all of the objects in the list should inherit from a common interface - for example
interface HasIdNum {
String getIdNum();
}
Now you list can be List<HasIdNum> and you can loop through it to find the object by id using:
for (HasIdNum hid: objList) {
if (hid.getIdNum().equals(idNumToFind) {
return hid;
}
}
return null;
To get the index rather than the object do:
for (int i=0;i<objList.size();i++) {
HasIdNum hid = objList.get(i);
if (hid.getIdNum().equals(idNumToFind) {
return i;
}
}
return -1;
Alternatively you can use reflection to query the methods of the object, but that will be much slower and much less safe as you lose all the compile time type checking.

sorting a string array and an int array [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am working on making a dating website on java. I want to find the three most compatible matches for a user. So i have an array of three ints and if a user is more compatible the least compatible score will be replaced. I do this using selection sort. I also need the references to be correct so i Can return the proper names. I can't figure our how to sort the string array. Thanks for the help and heres the code:
public void findMatches(String matchName)
{
String nameA = null;
String nameB = null;
String nameC = null;
int matchA = -1;
int matchB = -2;
int matchC = -3;
Member ref = userList.get(matchName);
if(ref.getDesiredAge()>=45 && ref.getDesiredSex().equalsIgnoreCase("Male"))
{
for(String na : userListMaleOld.keySet())
{
Member refA = userListMaleOld.get(na);
int numberOfMatches=findQuestionMatches(ref, refA);
int [] counts = {matchA, matchB, matchC};
String [] names = {nameA, nameB, nameC};
counts = doSelectionSort(counts);
if(numberOfMatches>counts[0]);
{
counts[0] = numberOfMatches;
?!?!?!?!?!??!??!??!WHAT HERE?!?!
}
Use a Map instead.
Concrete this means that you can do something like this:
Map<User, Integer> bestMatches = new HashMap<>();
void validateUser(User user, int value) {
if(bestMatches.size() < 3) {
bestMatches.put(User, 3);
return;
}
Map<User, Integer> newMap = new HashMap<User, Integer>();
User minValue = Collections.min(bestMatches.values());
if(value > minValue) {
for(Map.Entry<User, Integer> entry: bestMatches.entrySet()) {
if(entry.getValue() != minValue) {
newMap.put(entry.getKey(), entry.getValue());
}
}
newMap.put(user, value);
}
bestMatches = newMap;
}
It's probably not very optimized, but you can fix that as you wish. Basically just check if the value of the current user is higher than the lowest value among the existing users in the collection. If it is, create a new collection with the 2 other users and assign that to your first collection.
For large datasets this would be impractical, but we're talking about 3 users here so it shouldn't be an issue.
If these are actually supposed to be name / score pairs (i.e. scoreA is the score for nameA, scoreB is the score for nameB and so on), then the simple solution is something like this:
public class Score {
private String name;
private int score;
// Declare a constructor and getters
}
... and to use this appropriately. For instance, you could now sort a list or array of these Score objects, by name or by score.
Unfortunately, it is not possible to figure out what the code you've shown us is supposed to do, and how it is supposed interact with the rest of your code. Therefore, it is not entirely clear how you should modify your code to use this. And it maybe that you are best of starting over following Jeroen's advice and completely redesigning your data structures.

QueueAsLinkedList Implementation [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
This is my assignment program in data structure to implement a QueueAsArray. I want someone to guide me about this problem cause I don't have a strong background in java programming.
I'd like someone to give me guidance on what to do to compile and use this code in my main program.
public class QueueAsLinkedList extends AbstractContainer implements Queue
{
protected LinkedList list;
public QueueAsLinkedList ()
{ list = new LinkedList (); }
public void purge ()
{
list.purge ();
count = 0;
}
public Object getHead ()
{
if (count == 0)
throw new ContainerEmptyException ();
return list.getFirst ();
}
public void enqueue (Object object)
{
list.append (object);
++count;
}
public Object dequeue ()
{
if (count == 0)
throw new ContainerEmptyException ();
Object result = list.getFirst ();
list.extract (result);
--count;
return result;
}
public Enumeration getEnumeration()
{
return new Enumeration()
{
protected LinkedList.Element position = list.getHead();
public boolean hasMoreElements()
{
return position != null;
}
public Object nextElement()
{
if (position == null)
throw new NoSuchElementException();
Object result = position.getDatum();
position = position.getNext();
return result;
}
};
}
protected int compareTo (Comparable object)
{
AbstractContainer arg = (AbstractContainer) object;
long diff = (long) getCount() - (long) arg.getCount();
if (diff < 0)
return -1;
else if (diff > 0)
return +1;
else
return 0;
}
public boolean equals(Object object) {
LinkedList list_object = (LinkedList)object;
if(list_object.length != this.length) {
return false;
}
Element ptr = this.head;
Element list_object_ptr = list_object.head;
for(int i = 0; i < this.length; i++) {
if(list_object_ptr.getDatum () != ptr.getDatum ()) {
return false;
}
ptr = ptr.getNext ();
list_object_ptr = list_object_ptr.getNext ();
}
return true;
}
}
My suggestion to you is to read the existing LinkedList libraries source something you can easily find. I suggest you also read the source for ArrayList since you will be wrapping an array. Finally have a look at ArrayBlockingQueue because this is a Queue which wraps an array. This last class is the closest to what you want, but is the most complicated as it is concurrent and thread safe.
When you start writing a class, I suggest you start with something really simple and get that to compile. Using an IDE, it will show you whether the code will compile as you type the code and suggest corrections.
Then I would write a very simple unit test to test your very simple code. You can do this with just one method. (Some people suggest writing the test case first but I find this very hard unless you have written this sort of class before in which case you are not really writing the unit test first, just the first time for that code base)
Then add a second or third method and tests for those.
When it does something you don't understand, use your debugger to step through the code to see what each line does.
I would use an IDE such as Netbeans, Eclipse or IntelliJ CE. I prefer IntelliJ but Netbeans is perhaps the best for a beginner.
Download the IDE.
start a new project.
create a class and copy and paste the code into that class.
create another class which uses that class. This is your class.
BTW Did you write the class or was it given to you because it has more than a few unusual coding choices.
Comments on the code
Its a Queue which wraps a class which implements a Queue so delegation appears natural, but it doesn't appear to do this suggesting that LinkedList and Queue are not the standard LinkedList and Queue which is confusing.
it uses a field count which is not defined instead of the LinkedList.size().
dequeue accesses the LinkedList twice when once would be more efficient (as the standard library does)
It supports Enumeration instead of Iterator when Iterator was been the standard since Java 1.2 (1998)
compareTo is 0 when equals is false which is a bug.
it doen'ts support generics which the builtin one does.
compareTo only examines length so a queue with "A" and a queue with "Z" are compareTo == 0
equals uses this.head and this.length which are not fields.

Categories

Resources