I have been assigned the problem: Write a generic WeightedElement<E,W> class which stores an
element of type E and a weight of type W. It should implement Comparable relying on W's compareTo(). You should enforce that W itself is comparable.
So far I have made the class and implemented comparable but am encountering issue when making the compareTo() method for W. I have:
public class WeightedElement<E, W extends Comparable<W>> {
public E element;
public W weight;
public WeightedElement() {
element = this.element;
weight = this.weight;
}
public int compareTo(W data) {
if (this.weight == data.weight) {
return 0;
} else if (this.weight < data.weight) {
return 1;
} else {
return 1;
}
}
}
I am encountering the issue that when I compare the weights, the weight for data is not found. Also are there any other methods I have to create to properly have a class that implements comparable on one of the variables? Thank you for any help
You have the generics right, but just like WeightedElement itself, you have to call compareTo on the weights -- you can't use < or == to do comparisons.
public class WeightedElement<E, W extends Comparable<W>> implements Comparable<WeightedElement<E, W>> {
private final E element;
private final W weight;
public WeightedElement(E element, W weight) {
this.element = element;
this.weight = Objects.requireNonNull(weight, "'weight' should not be null");
}
#Override
public int compareTo(WeightedElement<E, W> other) {
return other == null ? 1 : weight.compareTo(other.weight);
}
}
Related
I need to sort a java list containing objects of type Hotel
List<Hotel> hotelList = new ArrayList<>();
Inside the class I do have the method
#Override
public List<Room> getAvailableRooms() {
return this.rooms;
}
I need to sort my hotelList by the price attribute found in Room class.
Any suggestions?
You should either use a Comparator or implement the Comparable interface
public class Foo implements Comparable<ToSort> {
private int val;
public Foo(int val){
this.val = val;
}
#Override
public int compareTo(ToSort f) {
if (val > f.val) {
return 1;
}
else if (val < f.val) {
return -1;
}
else {
return 0;
}
}
Read more here
https://dzone.com/articles/sorting-java-arraylist
I have a task to implement a collection of elements in ascending order, along with methods of adding an element to the collection, printing all the elements in the collection and loading an element (along with removing it from the collection, I can assume that I'm always loading the smallest one).
I'm supposed to use Comparable<T> interface.
Additionally, I need to implement a class hierarchy with the use of Comparable<T> interface (for example, it can be a hierarchy of military ranks).
Here is my code:
public class Collection<T extends Comparable<T>> implements Iterable<T>
{
public LinkedList<T> collection;
public Collection()
{
collection = new LinkedList<>();
}
public void addToList(T new)
{
int i = 0;
while (collection .get(i).compareTo(new) < 0)
{
i++;
}
collection.add(i, new);
}
public T load() throws EmptyStackException
{
if (collection.size() == 0)
{
throw new EmptyStackException();
}
T first = collection.getFirst();
collection.removeFirst();
return first;
}
public void printElements()
{
for (T obj : collection)
{
System.out.println(obj);
}
}
#Override
public Iterator<T> iterator()
{
return this.collection.iterator();
}
}
public abstract class Soldier implements Comparable<Soldier>
{
public String Name;
public abstract double Rank();
public int compareTo(Soldier S)
{
if(S.Rank() == this.Rank())
{
return 0;
}
else if (S.Rank() < this.Rank())
{
return 1;
}
else return -1;
}
}
public class General extends Soldier
{
public double Rank()
{
return 4;
}
public General(String Name)
{
this.Name = Name;
}
}
public class Colonel extends Soldier
{
public double Rank()
{
return 3;
}
public Colonel(String Name)
{
this.Name = Name;
}
}
public class Corporal extends Soldier
{
public double Rank()
{
return 2;
}
public Corporal(String Name)
{
this.Name = Name;
}
}
public class Private extends Soldier
{
public double Ranga()
{
return 1;
}
public Private(String Name)
{
this.Name = Name;
}
}
When I tried to run some tests I got an error "Index out of bounds". What is actually happening here? I suspect that I can't add an element to my collection properly. Is this code correct?
The problem can be isolated here:
public LinkedList<T> collection;
public Collection()
{
collection = new LinkedList<>();
}
public void addToList(T new)
{
int i = 0;
while (collection.get(i).compareTo(new) < 0)
{
i++;
}
collection.add(i, new);
}
The first time you try to add an element, you pass zero to collection.get. This attempts to get the first element (as Lists are zero-indexed) but there is no first element to get.
Additionally, 'new' is a keyword in Java and cannot be used as an identifier.
Your problem lies in this loop
while (collection .get(i).compareTo(new) < 0)
{
i++;
}
It will try to get a new element even if i is equal to or greater than the length of the collection. You need to check that it is not.
while (i < collection.size() && collection .get(i).compareTo(new) < 0)
{
i++;
}
I created a priority queue which contains QueueItem objects. But even though I have already implemented getPriority() in the QueueItem class, it still says cannot resolve method getPriority() in the method insert() of the PriorityQueue class.
Here is my PriorityQueue class:
public class PriorityQueue<QueueItem> implements Iterator<QueueItem> {
private int maxSize;
private int size;
private Map<Integer, List<QueueItem>> pq;
public PriorityQueue(int maxSize) {
if (maxSize < 0) throw new IllegalArgumentException();
this.maxSize = maxSize;
pq = new HashMap<Integer, List<QueueItem>>();
}
public boolean isEmpty() {
return size == 0;
}
public int size() {
return size;
}
public void insert (QueueItem item) {
int priority = item.getPriority(); //here is where the problem occured
// pq.get(priority)
}
}
Here is my QueueItem class:
public class QueueItem implements Comparable{
private int priority;
private Object value;
public QueueItem() {
priority = -1;
value = null;
}
public QueueItem(int priority, Object value) {
this.priority = priority;
this.value = value;
}
public int getPriority() {
return priority;
}
public Object getValue() {
return value;
}
public int compareTo(Object o) {
if (!(o instanceof QueueItem)) throw new ClassCastException();
if (((QueueItem)o).getPriority() == -1) throw new NullPointerException();
return priority - ((QueueItem) o).getPriority();
}
}
As you can see, the method getPriority() simply returns an integer priority.
I appreciate in advance if anyone could point out the error I have made. Thanks.
OH. It was staring me in the face.
public class PriorityQueue<QueueItem> implements Iterator<QueueItem> {
// ^^^^^^^^^^^
You're declaring a type variable here with the same name as the class QueueItem which shadows it.
So I think you just want to remove that:
public class PriorityQueue implements Iterator<QueueItem> {
If you intended for PriorityQueue to be generic then I'm not sure exactly what you need to do to fix it. Perhaps you would want something like this:
public class PriorityQueue<E> implements Iterator<QueueItem<E>> {
...
private Map<Integer, List<QueueItem<E>>> pq;
...
}
public class QueueItem<E> implements Comparable<QueueItem<E>> {
...
private E value;
...
}
As a side note, using the raw type Comparable isn't good. Even with the non-generic class QueueItem you should have implements Comparable<QueueItem>.
Say I have arraylist A and to compare 2 objects of A I do a.getDistanceFromPlayer() < b.getDistanceFromPlayer().
I want to now have list B which will have all of A's objects, but sorted where the first object is closest to player, and last object is furthest.
What might be the fastest way to do this?
Thanks
Have A implement Comparable and then define the method compareTo(Object other) like so:
public int compareTo(Object other) {
if( this.getDistanceFromPlayer() < other.getDistanceFromPlayer() ) {
return -1;
} else if( this.getDistanceFromPlayer() > other.getDistanceFromPlayer()) {
return 1;
}
return 0;
}
Now you can call Collections.sort() on your list of objects
Use Collections.sort with a custom comparator.
eg.
public class DistanceComparator implements Comparator<Integer>{
#Override
public int compare(YourObject o1, YourObject o2) {
if (o1.getDistanceFromPlayer() > o2.getDistanceFromPlayer())
{
return 1;
}
else if (o1.getDistanceFromPlayer() < o2.getDistanceFromPlayer())
{
return -1;
}
return 0;
}
}
Then in your program, call
Collections.sort(YourArrayInstance, new DistanceComparator())
You should make your class implement Comparable.
Then you can use Collections.sort() to sort your List.
If you want a sorted List AND an unsorted List, you'll have to make a copy.
Another option is to create a Comparator.
If you read the documentation for Collections, you'll see it has two sort methods.
One bases the sort on the objects' compareTo method (ie their "natural order").
The other bases the sort on a Comparator that is passed as the second argument.
Here's a link to another question that provides an example implementation of Comparable:
Example implementation of Comparable
Use a Custom Comparator :
B = Collections.sort(A, new CustomComparator());
public class CustomComparator implements Comparator<ClassA> {
#Override
public int compare(final ClassA a, final ClassA b) {
//Make sure you check that neither a nor b are null..
//..
if (a.getDistanceFromPlayer() < b.getDistanceFromPlayer()) {
return 1;
} else if (a.getDistanceFromPlayer() > b.getDistanceFromPlayer()) {
return -1;
}
return 0;
}
}
You can use a custom Comparator and sort your ArrayList, like this:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
class Main {
public static class Player {
private final float distance;
public Player (final float position) {
this.distance = position;
}
public float getDistanceFrom () {
return distance;
}
#Override
public String toString() {
return "Player [distance=" + distance + "]";
}
}
public static void main(String[] args) throws Exception {
final ArrayList<Player> players = new ArrayList<Player> ();
players.add (new Player (2));
players.add (new Player (5));
players.add (new Player (-3));
players.add (new Player (1));
Collections.sort(players, new Comparator<Player> () {
#Override
public int compare(Player o1, Player o2) {
final float distance1 = o1.getDistanceFrom();
final float distance2 = o2.getDistanceFrom();
return (int) Math.signum (distance1 - distance2);
}
});
System.out.println(players);
}
}
And a fiddle for it.
Could someone please help me out with the following problem in java. I have a simple class defined as below:
public class Expr {
public long total_apparitions;
public String expression=new String();
public Expr(long total,String expr){
this.total_apparitions=total;
this.expression=expr;
}
public void increment(long aparitions){
total_apparitions+=aparitions;
}
}
I want to sort an array of Expr objects by the total_apparitions field, using the Arrays.sort built-in function. How do I specify to the Arrays.sort function the comparison factor? Thanks a lot.
As #Jason Braucht said, implement Comparable like this:
public class Expr implements Comparable {
...
public int compareTo(Object o) {
if(this.total_apparitions > ((Expr) o).total_apparitions)
return 1;
else if(this.total_apparitions < ((Expr) o).total_apparitions)
return -1;
return 0;
}
}
Make Expr implement java.lang.Comparable
Edit - Should have provided an example (others already did). Here's a full sample using generics.
public class Expr implements Comparable<Expr>
{
public long total_apparitions;
public String expression = new String();
public Expr(long total, String expr)
{
this.total_apparitions = total;
this.expression = expr;
}
public void increment(long aparitions)
{
total_apparitions += aparitions;
}
public int compareTo(Expr o)
{
if (total_apparitions > o.total_apparitions)
{
return 1;
}
else if (total_apparitions < o.total_apparitions)
{
return -1;
}
else
{
return 0;
}
}
}
As an alternative to implementing Comparable, you can pass a Comparator instance to the Arrays.sort() method. The advantage of doing it this way is that it allows you to have different concepts of sorting an array of objects of this type (say you might want to sort by the name later, in which case you just need a different implementation of the comparator).
For example:
public class ByApparationsComparator implements Comparator<Expr> {
public int compare(Expr first, Expr second) {
if (first.total_apparitions > second.total_apparitions) {
return 1;
} else if (first.total_apparitions < second.total_apparitions) {
return -1;
} else {
return 0;
}
}
}
Then you can say:
Arrays.sort(exprArray, new ByApparationsComparator());