I want to compare a collection (ArrayList) of elements if they are the same type. In the beginning I do not know what type the elements are (generic types), so I decided to use Object type. But I still cannot compare them. The problem is in the function triplesort().The warning is:
Operator '>' cannot be applied to 'java.lang.Object', 'java.lang.Object'. If you have any possible solutions to that problem and you let me know, I would be grateful. <3
Triple.java
import java.util.ArrayList;
public class Triple<T, S, U> {
private T t;
private S s;
private U u;
private ArrayList<Object> array = new ArrayList<Object>();
Triple(T t, S s, U u) {
setT(t);
setS(s);
setU(u);
array.add(this.t);
array.add(this.s);
array.add(this.u);
}
public void setT(T t) {
this.t = t;
}
public void setS(S s) {
this.s = s;
}
public void setU(U u) {
this.u = u;
}
public T getFirst() {
return t;
}
public S getSecond() {
return s;
}
public U getThird() {
return u;
}
public String toString() {
return t + "\n" + s + "\n" + u + "\n";
}
public boolean isHomogeneous() {
return t.getClass() == s.getClass() && t.getClass() == u.getClass();
}
public void tripleSort() {
try {
for (int i = 1; i < array.size(); ++i) {
Object key = array.get(i);
int j = i - 1;
while (j > -1 && array.get(i) > key) {
array.set(j + 1, array.get(j));
j--;
}
array.set(j + 1, key);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
There are two main issues with code you've provided:
Relational operators <, <=, >, >= can be used only to compare numeric primitive types. Obviously, you can use it with objects.
To compare reference types you can use Comparator or these objects can implement Comparable interface (i.e. they basically are aware how to compare themselves). But it doesn't make since to compare BigDecimal and Boolean, or String and HashMap, how would you approach that? For that reason, these interfaces are generic and Comparator<T> can't be used with objects of type U.
That said, your Triple<T, S, U> would not be able to do a lot with these objects belonging to different type (definitely you can't sort them).
Hence, if you need a data-carrier holding references of three distinct types, that fine. It's still can be useful, but don't expect from it much.
A Java 16 record fits in this role perfectly well:
public record Triple<T, S, U>(T first, S second, U third) {}
But if you need to able to operate with these values comparing them with one another then consider changing the Triple to hold only elements of type T.
Here's an example of how it might be implemented:
public static class Triple<T> {
private List<T> list = new ArrayList<>(3);
private Comparator<T> comp;
private Triple(T first, T second, T third, Comparator<T> comp) { // no way and no need to invoke this constructor outside the class
this.comp = comp;
Collections.addAll(list, first, second, third);
}
public static <T> Triple<T> getInstance(T first, T second, T third, Comparator<T> comp) {
Triple<T> triple = new Triple<>(first, second, third, comp);
triple.init();
return triple;
}
public void init() {
list.sort(comp);
}
public T getFirst() {
return list.get(0);
}
public T getSecond() {
return list.get(1);
}
public T getThird() {
return list.get(2);
}
public boolean isHomogeneous() {
return comp.compare(getFirst(), getSecond()) == 0
&& comp.compare(getFirst(), getThird()) == 0
&& comp.compare(getSecond(), getThird()) == 0;
}
public String toString() {
return list.stream().map(T::toString).collect(Collectors.joining("\n"));
}
}
Usage example:
Let's consider a Triple storing integer value in Descending order.
public static void main(String[] args) {
Triple<Integer> intTriple = Triple.getInstance(5, 3, 12, Comparator.reverseOrder());
System.out.println(intTriple);
}
Output:
12
5
3
Related
I'm trying to write a Linear List based on arrays, but make the list be able to store any value by using Java Generics. This way I can create other programs that utilize it, but pass in different data types. I'm not entirely sure how to do this, any help would be appreciated.
I guess Im struggling trying to set it up and create the functions. The generic type really messes me up.
For example, trying to add a removeFirst() function, I cant use a loop like this:
for (int i = 0; i < n - 1; i++)
newList[i] = newList[i + 1];
— as it says The type of the expression must be an array type but it resolved to ArrayList.
Fair warning, I'm still learning data structures. This is what I have so far:
import java.util.ArrayList;
public class LinearList<T> {
private static int SIZE = 10;
private int n = 0;
private final ArrayList<T> newList = new ArrayList<T>(SIZE);
private T t;
public void set(T t) {
this.t = t;
}
public T get() {
return t;
}
public void add(T value, int position) {
newList.add(position, value);
n++;
}
public void addFirst(T value) {
newList.add(0, value);
n++;
}
public void removeLast() {
T value = null;
for (int i = 0; i < newList.size(); i++)
value = newList.get(i);
newList.remove(value);
n--;
}
public void removeFirst() {
newList.remove(0);
n--;
}
public T first() {
return newList.get(0);
}
public T last() {
int value = 0;
for (int i = 0; i < newList.size() - 1; i++)
value++;
return newList.get(value);
}
public int count() {
return n;
}
public boolean isFull() {
return (n >= SIZE);
}
public boolean isEmpty() {
return (n <= 0);
}
//part 4
public void Grow() {
int grow = SIZE / 2;
SIZE = SIZE + grow;
}
public void Shrink() {
int grow = SIZE / 2;
SIZE = SIZE - grow;
}
public String toString() {
String outStr = "" + newList;
return outStr;
}
}
A good start would be to make it non-generic with a class you are comfortable with, such as an Integer.
Once you have it set up, you can then make it generic by adding <T> to the class name, then replacing all references of Integer with T.
public class MyArray{ becomes public class MyArray<T>{
public Integer add(Integer value){ becomes public T add(T value){
See What are Generics in Java? for more help
I want to compare two Java classes.
class ClassComparator implements Comparator<Class> {
#Override
public int compare(Class arg0, Class arg1) {
return ....;
}
}
I could just compare class names, but I want parent classes be "smaller" than classes derived from them. And I want this less-than relation to be transitive and work for any two classes. (To be honest, in my real problem one class will always be a superclass of another, but I want some general-case code because in theory this can change.)
Maybe this is already done and someone can share a code snippet?
What comes to my mind is: if none of the classes is derived from another, find their two superclasses derived from the common ancestor, and compare their names. (Hmmm, it can even support interfaces, if any object class is greater than any interface.)
You can also compare classes that are not in one hierarchy by how deep are they and far away from Object class.
class ClassComparator implements Comparator<Class> {
#Override
public int compare(Class arg0, Class arg1) {
boolean arg0assignable = arg0.isAssignableFrom(arg1);
boolean arg1assignable = arg1.isAssignableFrom(arg0);
if (arg0assignable == arg1assignable && arg0assignable) {
return 0;
} else if (arg0assignable) {
return -1;
} else if (arg1assignable){
return 1;
} else {
return compareByDistanceToObject(arg0, arg1);
}
}
private int compareByDistanceToObject(Class arg0, Class arg1) {
int distanceToObject0 = getDistance(arg0);
int distanceToObject1 = getDistance(arg1);
if (distanceToObject0 == distanceToObject1) {
return 0;
} else if (distanceToObject0 < distanceToObject1) {
return -1;
} else {
return 1;
}
}
private int getDistance(Class clazz) {
if (clazz == Object.class) {
return 0;
}
return 1 + getDistance(clazz.getSuperclass());
}
I think you should be able to just do:
new Comparator<Class>() {
#Override
public int compare(Class o1, Class o2) {
if (o1 == o2)
return 0;
if (o1.isAssignableFrom(o2))
return -1;
if (o2.isAssignableFrom(o1))
return 1;
return o1.getSimpleName().compareTo(o2.getSimpleName());
}
}
Your constraints do not yield an ordered set.
class C {}
class B {}
class A extends C {}
Then you have:
A < B
B < C
C < A
EDIT: Since Comparator imposes a total ordering, there is no solution to your question.
EDIT 2: However, if there is no solution within your constraints, you can change them. If your objective is to define a total order among classes, so that a superclass is always less-than a subclass (ignoring interfaces) (i.e. we don't require to compare class names anymore), you can:
make a list of the (linear) hierarchy for each class
compare the resulting lists
I just realized that comparing class names was not a requirement in your question.
Let's take an example:
class C {}
class B {}
class A extends C {}
class D extends A {}
List the hierarchy of each class:
C → (C)
B → (B)
A → (C, A)
D → (C, A, D)
Then, you get a total order:
B → (B)
C → (C)
A → (C, A)
D → (C, A, D)
So, we want to define a total order on classes such that any parent class/interface is "smaller" than any derived class/interface.
The solution is:
Any interface class is smaller than any object class.
to compare two interfaces, we compare the number of their superinterfaces. If they are equal, we compare their names.
to compare two object classes, we compare the number their of superclasses. If they are equal, we compare their names.
Why this is correct. A derived class always have more ancestors than any of its its superclasses. So if we compare the number of ancestors, we guarantee that superclasses go before their descendants. And as to the ordering within the group of classes that have N parents, any ordering will do, alphabetic ordering is ok.
class ClassComparator implements Comparator<Class<?>> {
#Override
public int compare(Class<?> first, Class<?> second) {
int areInterfaces = first.isInterface() ? 1 : 0;
areInterfaces += second.isInterface() ? 2 : 0;
switch (areInterfaces) {
case 1 + 2:
return compareNumbersThenNames(getInterfaceCount(first), getInterfaceCount(second), first, second);
case 0 + 2:
return -1;
case 1 + 0:
return 1;
case 0 + 0:
default:
return compareNumbersThenNames(getAncestorCount(first), getAncestorCount(second), first, second);
}
}
private int compareNumbersThenNames(int f, int s, Class<?> first, Class<?> second) {
if (f-s != 0) {
return f-s;
} else {
return compareByName(first, second);
}
}
private int getAncestorCount(Class<?> objectClass) {
int res=0;
for (Class<?> i = objectClass; i != null ; i = i.getSuperclass()) {
res++;
}
return res;
}
private int getInterfaceCount(Class<?> interfaceClass) {
Set<Class<?>> superInterfaces = new HashSet<>();
addSuperinterfaces(superInterfaces, interfaceClass);
return superInterfaces.size();
}
private void addSuperinterfaces(Set<Class<?>>set, Class<?>interfaceClass) {
for (Class<?> s : interfaceClass.getInterfaces()) {
if (!set.contains(s)) {
set.add(s);
addSuperinterfaces(set, s);
}
}
}
private int compareByName(Class<?> a, Class<?> b) {
int res = a.getSimpleName().compareTo(b.getSimpleName());
if (res != 0) { return res; }
res = a.getName().compareTo(b.getName());
// we do not support different class loaders
return res;
}
}
A bit late to post (Orest Savchak posted a very similar-but-not-quite-the-same answer a bit before), but you can find the closest common ancestor and then calculate each class' distance to this object. All classes (except for classes for primitives) have a common ancestor (at the very worst, the Object class), and we can use this information in order to ensure there is some ordering: At the worst, you can simply compare the two classes on their "depth" in their respective inheritance hierarchies rooted from Object.
Additionally, if while navigating the class hierarchy one compared class is found, the other class is then proven to be a child and thus is "greater" than the other one:
public final class InheritanceDepthComparator<T> implements Comparator<Class<? extends T>> {
private static class B {};
private static class C {};
private static class A extends C {};
private static <SUP, SUB extends SUP> int calculateInheritanceDistance(final Class<? extends SUB> o1,
final Class<? extends SUP> o2) {
int result = 0;
Class<?> o1Parent = o1;
do {
o1Parent = o1Parent.getSuperclass();
result++;
} while (!Objects.equals(o1Parent, o2));
return result;
}
#Override
public int compare(final Class<? extends T> o1, final Class<? extends T> o2) {
int result = 0;
if (!o1.equals(o2)) {
// Walk up the inheritance hierarchy
int o1Depth = -1;
Class<?> o1Parent = o1;
do {
o1Parent = o1Parent.getSuperclass();
o1Depth++;
if (o1Parent.equals(o2)) {
// The first compared object is a child of the second and
// therefore "greater" than it
result = 1;
break;
} else if (o1Parent.isAssignableFrom(o2)) {
// Found the common ancestor class; At least by reaching
// "Object", this should always be executed anyway
// TODO: Check performance and see if manually going up the tree for o2 within this while loop itself is not faster
final int o2Depth = calculateInheritanceDistance(o2, o1Parent);
result = Integer.compare(o1Depth, o2Depth);
break;
}
} while (o1Parent != null);
}
return result;
}
public static void main(final String[] args) {
final InheritanceDepthComparator<Object> cComp = new InheritanceDepthComparator<>();
System.out.println("Parent compared to child: " + cComp.compare(C.class, A.class));
System.out.println("Child compared to parent: " + cComp.compare(A.class, C.class));
System.out.println("C (child) Compared to Object (parent): " + cComp.compare(A.class, Object.class));
System.out.println("Sibling classes:" + cComp.compare(A.class, B.class));
}
}
You can then use this Comparator in a chain in order to handle sibling classes:
final Comparator<Class<?>> cmp = new InheritanceDepthComparator<>().thenComparing(Class::getName);
I am writing a program that inherits some traits from MyStackGeneric called MyStackInteger. I am almost done with the assignment, but I am running into an issue. As soon as I get my two variables in the method binaryOperator, it tries to add, subtract or multiply strings which returns and error. I've tried type casting and moving things around but I cannot get it to work. One of the constraints of my work is that all the methods that are currently in MyStackGeneric have to stay in there. I cannot have them in MyStackInteger as we are going to be using this for Complex numbers in the future.
class `MyStackInteger`:
import java.util.ArrayList;
import java.util.Scanner;
import java.util.Iterator;
public class MyStackInteger extends MyStackGeneric<java.lang.Integer>{
//Creates a new ArrayList and runs readInput as long as there is input
public static void main(String[] args){
MyStackInteger my = new MyStackInteger(){};
my.readInput(new Scanner(System.in));
}
//Subtracts two variables
#Override
protected java.lang.Integer minus(java.lang.Integer o1, java.lang.Integer o2){
o2 = o2-o1;
return o2;
}
//Multiplies two variables
#Override
protected java.lang.Integer multiply(java.lang.Integer o1, java.lang.Integer o2){
o2 = o2*o1;
return o2;
}
//Creates a new element in the Array
#Override
protected java.lang.Integer newElement(java.lang.String w){
return new Integer(w);
}
//Adds two variables
#Override
protected java.lang.Integer plus(java.lang.Integer o1, java.lang.Integer o2){
o2 = o2+o1;
return o2;
}
//Adds a zero to the array
#Override
protected java.lang.Integer zero(){
Integer blank = 0;
return blank;
}
}
class MyStackGeneric<E>:
abstract class MyStackGeneric<E> extends ArrayList<E>{
//Generics being implemented by MyStackInteger
protected abstract E multiply(E o1, E o2);
protected abstract E minus(E o1, E o2);
protected abstract E plus(E o1, E o2);
protected abstract E zero();
protected abstract E newElement(java.lang.String w);
//Grabs the top element of the ArrayList
public E peek(){
return this.get(getSize()-1);
}
//Removes the top element of the ArrayList
public E pop(){
E o = this.get(getSize()-1);
this.remove(getSize()-1);
return o;
}
//Pushes an element onto the ArrayList
public void push(E o) {
this.add(o);
}
//Makes the ListArray A string
#Override
public String toString() {
return "stack: " + this.toString();
}
//Iterates while there is input
public void readInput(Scanner s) {
while (s.hasNext()) {
String s2 = s.next();
//Pushes any numerical input to the stack
if (s2.matches("[+-]?\\d+")) {
push((E) s2);
//Goes to binaryOperator if +, - or * is implemented
} else if (("+".equals(s2)) ||
("-".equals(s2)) ||
("*".equals(s2))) {
binaryOperator(s2);
//Prints the stack
} else if (s2.matches("p")) {
print();
//Runs an error if the input is too long
} else if (s2.length() > 1) {
System.out.println("Exception: too long: " + s2);
//Runs an error if there is one unknown char
} else if (s2.length() == 1) {
System.out.println("Exception: Unknown Command " + s2);
}
}
}
//Prints the stack
public void print(){
System.out.println("Print Stack: ");
Iterator<E> s = this.iterator();
while(s.hasNext()){
System.out.print(s.next() + (s.hasNext() ? ", " : "\n" ));
System.out.println("");
}
}
//Checks if the ArrayList is empty
public boolean empty(){
return this.isEmpty();
}
//Gets the total size of the ArrayList
public int getSize(){
return this.size();
}
//Tries to grab the top two elements of the ArrayList, then execute a
//arithmetic operation on them.
public void binaryOperator(java.lang.String op){
E var1;
E var2;
boolean exist = true;
try {
var1 = peek();
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Exception: Need two operands");
var1 = null;
exist = false;
}
if (exist)
pop();
try {
var2 = peek();
}catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Exception: Need two operands");
var2 = null;
exist = false;
}
if (exist)
pop();
//This is where the program breaks. At this point, both var1
//and var2 are Strings so when it tries to run plus or minus
//or multiply, it returns the error of not being able to turn
//a string into an int.
if ("+".equals(op)){
push(plus(var1, var2));
}
if ("-".equals(op)){
push(minus(var1, var2));
}
if ("*".equals(op)){
push(multiply(var1, var2));
}
}
}
if (s2.matches("[+-]?\\d+")) {
push((E) s2);
You cannot do this. You cannot take a String and execute an arbitrary cast on it. If you were paying attention to the compiler you would see the warning message
Type safety: Unchecked cast from String to E
The primary issue is with your design. The method readInput has no business being in the MyStackGeneric class. The class should do one thing only, which is serve as the base for implementing concrete stacks. Input and output should be handled by the users of the class, who could do the correct parsing/conversion for the input data.
Or, to put it another way, converting input data to match the generic type requires information (the concrete parameter type) that is not available to the MyStackGeneric class because of type erasure. You could put concrete versions of readInput() in your concrete classes. For MyStackInteger those lines would become
if (s2.matches("[+-]?\\d+")) {
push(Integer.valueOf(s2));
But that still violates the single-responsibility principle.
I have some object in Java (say a Double), and I need a list of length n, each of whose elements is a reference to that Double. I'd like an idiom for doing this, hopefully but not necessarily without using O(1) only memory.
You can use
java.util.Collections.nCopies(n, value).
What about creating a data structure for this purpose?
Something like that:
import java.util.HashMap;
public class SpecialArray {
private HashMap<Integer, Double> elements;
private Double specialElement;
private int size;
public SpecialArray(Double specialElement, int size) {
this.elements = new HashMap<Integer, Double>();
this.specialElement = specialElement;
this.size = size;
}
public Double get(int index) {
if(index<0 || index>=size) {
return null;
}
if(elements.containsKey(index)) {
return elements.get(index);
}
return specialElement;
}
public boolean add(Double d, int index) {
if(index<0 || index>=size || elements.containsKey(index)) {
return false;
}
elements.put(index, d);
return true;
}
}
This is not a full example, of course, and can be written with generic types.
But if you have a few other elements in your list, then this can be useful, I think.
Collections.fill()
might help you
I have defined my own compare function for a priority queue, however the compare function needs information of an array. The problem is that when the values of the array changed, it did not affect the compare function. How do I deal with this?
Code example:
import java.util.Arrays;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Scanner;
public class Main {
public static final int INF = 100;
public static int[] F = new int[201];
public static void main(String[] args){
PriorityQueue<Integer> Q = new PriorityQueue<Integer>(201,
new Comparator<Integer>(){
public int compare(Integer a, Integer b){
if (F[a] > F[b]) return 1;
if (F[a] == F[b]) return 0;
return -1;
}
});
Arrays.fill(F, INF);
F[0] = 0; F[1] = 1; F[2] = 2;
for (int i = 0; i < 201; i ++) Q.add(i);
System.out.println(Q.peek()); // Prints 0, because F[0] is the smallest
F[0] = 10;
System.out.println(Q.peek()); // Still prints 0 ... OMG
}
}
So, essentially, you are changing your comparison criteria on the fly, and that's just not the functionality that priority queue contracts offer. Note that this might seem to work on some cases (e.g. a heap might sort some of the items when removing or inserting another item) but since you have no guarantees, it's just not a valid approach.
What you could do is, every time you change your arrays, you get all the elements out, and put them back in. This is of course very expensive ( O(n*log(n))) so you should probably try to work around your design to avoid changing the array values at all.
Your comparator is only getting called when you modify the queue (that is, when you add your items). After that, the queue has no idea something caused the order to change, which is why it remains the same.
It is quite confusing to have a comparator like this. If you have two values, A and B, and A>B at some point, everybody would expect A to stay bigger than B. I think your usage of a priority queue for this problem is wrong.
Use custom implementation of PriorityQueue that uses comparator on peek, not on add:
public class VolatilePriorityQueue <T> extends AbstractQueue <T>
{
private final Comparator <? super T> comparator;
private final List <T> elements = new ArrayList <T> ();
public VolatilePriorityQueue (Comparator <? super T> comparator)
{
this.comparator = comparator;
}
#Override
public boolean offer (T e)
{
return elements.add (e);
}
#Override
public T poll ()
{
if (elements.isEmpty ()) return null;
else return elements.remove (getMinimumIndex ());
}
#Override
public T peek ()
{
if (elements.isEmpty ()) return null;
else return elements.get (getMinimumIndex ());
}
#Override
public Iterator <T> iterator ()
{
return elements.iterator ();
}
#Override
public int size ()
{
return elements.size ();
}
private int getMinimumIndex ()
{
T e = elements.get (0);
int index = 0;
for (int count = elements.size (), i = 1; i < count; i++)
{
T ee = elements.get (i);
if (comparator.compare (e, ee) > 0)
{
e = ee;
index = i;
}
}
return index;
}
}