i am trying to sort a TreeSet of objects ("Etudiant") using Comparator interface . This the Comparator implementation:
import java.util.Comparator;
public class TriParNom implements Comparator<Etudiant>{
public int compare(Etudiant o1, Etudiant o2) {
return o1.getNom().compareTo(o2.getNom());
}
}
here is the the TreeSet declaration and the call of the comparator in the main :
TreeSet<Etudiant> University= new TreeSet<Etudiant>(new TriParNom());
the error i get in the main class when i declare the TreeSet and call the comparator ,is : no suitable constructor found for TreeSet(TriParNom) .
Any solutions please ? thanks in advance .
I tried a very simple implementation based on the information you provided, and I give you my results:
The Etudiant class is a very simple pojo
public class Etudiant {
private String nom;
public String getNom() {
return nom;
}
public void setNom(String nom) {
this.nom = nom;
} }
The TriParNom class is the plain Comparator you described:
import java.util.Comparator;
public class TriParNom implements Comparator<Etudiant> {
#Override
public int compare(Etudiant o1, Etudiant o2) {
return o1.getNom().compareTo(o2.getNom());
}
}
And here is a simple class with an entry point and a sample method to exercise the newly created treeset
import java.util.TreeSet;
public class Main {
public static void main(String[] args) {
TreeSet<Etudiant> u = new TreeSet<>(new TriParNom());
System.out.printf("size? %d%n", u.size());
}
}
Execution results follow:
Apparently, there are no compilation errors either.
If your code matches to the snippet given below, then it should run fine without problems. The moment you remove the part implements Comparator<Etudiant> from class TriParNom, you will get the error indicating suitable constructor not found. Now, one another silly way it could happen if you haven't recompiled your classes after you implemented the comparator to your TriParNom - but that's too obvious. Have your class that contins main method(that declares Treeset) imported java.util.TreeSet ?
import java.util.Comparator;
import java.util.TreeSet;
public class TreesetCheck {
public static void main(String[] args) {
TreeSet<Etudiant> University= new TreeSet<Etudiant>(new TriParNom());
}
}
class TriParNom implements Comparator<Etudiant>{
public int compare(Etudiant o1, Etudiant o2) {
return o1.getNom().compareTo(o2.getNom());
}
}
class Etudiant {
public String getNom() {
// TODO Auto-generated method stub
return "some";
}
}
Related
I know that we can retrieve a variable's value by simply writing get methods and return var;. However, is there another way to write a get method to return information on the fields instead? If so, how does one access it. For example, if I have a planeNumber and I want to check it against another object's planeNumber, is there a way to use a boolean to check instead of writing public int getPlaneNumber()?
Seems like you are wanting to implement the Comparable interface? https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html
That is it looks like you have an attribute, planeNumber, that you want to use to compare the classes?
Maybe you want something like this
import java.util.Comparator;
import java.util.Objects;
public class Airplane implements Comparable<Airplane> {
private final int planeNumber;
public Airplane(final int planeNumber) {
this.planeNumber = planeNumber;
}
public final int getPlaneNumber() {
return planeNumber;
}
#Override
public int compareTo(final Airplane o) {
return Objects.compare(this, o, Comparator.comparing(Airplane::getPlaneNumber));
}
public static void main(final String... args) {
System.out.println(new Airplane(1).compareTo(new Airplane(2)));
System.out.println(new Airplane(100).compareTo(new Airplane(100)));
System.out.println(new Airplane(1000).compareTo(new Airplane(100)));
}
}
-1
0
1
You could add a method comparing the field values to your class like this (omitting null check in the methods):
class Scratch {
public static void main(String[] args) {
ObjectWithPlaneNumber o1 = new ObjectWithPlaneNumber(42);
ObjectWithPlaneNumber o2 = new ObjectWithPlaneNumber(42);
ObjectWithPlaneNumber o3 = new ObjectWithPlaneNumber(11);
System.out.println(o1.hasSamePlaneNumber(o2));
System.out.println(o1.hasSamePlaneNumber(o3));
}
static class ObjectWithPlaneNumber {
private final int planeNumber;
public ObjectWithPlaneNumber(int planeNumber) {
this.planeNumber = planeNumber;
}
public boolean hasSamePlaneNumber(ObjectWithPlaneNumber other) {
return this.planeNumber == other.planeNumber;
}
}
}
I want to implement a class that instantiates generic types.
public class DisjointSet<T extends Set<E>, E> {
private final Class<T> setType;
public DisjointSet(Class<T> setClass) {
this.setType = setClass;
}
public void doSomething(E Element) {
T set = setClass.newInstance();
set.add(element);
}
}
I tried instantiating the class like this:
DisjointSet<HashSet<Integer>, Integer> disjointSet = new DisjointSet<>(HashSet<Integer>.class);
However using .class on a generic type does not seem to be allowed. How would I correctly pass the required Class of a generic type to the constructor?
Not sure it is good to expose the inner set type (Hash versus other) in the parameterized type.
Actually due to type erasure you can't instantiate parameterised types directly, but you can pass in a factory,
package langGenerics;
import java.util.HashSet;
import java.util.Set;
public class UseGenerics {
public static void main(String[] args) {
SetFactory<Integer> setFactory = HashSet::new;
DisjointSet<Integer> disjointSet = new DisjointSet<>(setFactory);
disjointSet.doSomething( 123 );
}
}
interface SetFactory<T> { Set<T> get(); }
class DisjointSet<T> {
private SetFactory<T> setFactory;
public DisjointSet(SetFactory<T> setFactory) {
this.setFactory = setFactory;
}
public void doSomething(T item) {
Set<T> set = setFactory.get();
set.add(item);
}
}
If you really want to init your own set storage, then I suggest you to pass Supplier to your constructor:
public static class DisjointSet<T extends Set<E>, E> {
T set;
public DisjointSet(Supplier<T> supplier) {
set = supplier.get();
}
public void doSomething(E element) {
set.add(element);
}
}
Then use it:
DisjointSet<HashSet<Integer>, Integer> set = new DisjointSet<>(HashSet::new);
if this is what you wanted,
public class DisjointSet<T extends Set<E>, E> {
private final Class<T> setType;
public DisjointSet(Class<T> setClass) {
this.setType = setClass;
}
public static void main(String[] args) {
DisjointSet<HashSet<Integer>, Integer> disjointSet = new DisjointSet(new HashSet<Integer>().getClass());
}
}
I want to write a compare class so that I can sort a list of elements using this comparator later on, but i get an error.
The code looks as such:
class Elem {
public String user_name;
public String given_name;
public String getGivenName() {
return given_name;
}
}
class Compare implements Comparator<Elem> {
public int compare(Elem o1, Elem o2) {
return o1.getGivenName().compareTo(o2.getGivenName());
}
}
This gives me the error:
Elem cannot be resolved to a type
I'm not sure how I can fix this error.
It means that the compiler cannot find class Elem.
Don't forget to import it at the top of your java class in case the Elem class is in the different package.
Also make sure you don't have any typo.
The code above compiles cleanly at my machine (Java 7) with the added import.
import java.util.Comparator;
class Elem {
public String user_name;
public String given_name;
public String getGivenName() {
return given_name;
}
}
class Compare implements Comparator<Elem> {
public int compare(Elem o1, Elem o2) {
return o1.getGivenName().compareTo(o2.getGivenName());
}
}
public class C1 implements Iterable {
private LinkedList list;
public static class NC1 {
...
}
...
x public Iterator iterator() {
return list.iterator();
}
}
but eclipse whines (at the x-ed line):
- The return type is incompatible with Iterable<NC1>.iterator()
- implements java.lang.Iterable<NC1>.iterator
I don't understand where the mistake is. Can someone help?
You need to change NC1 to C1.NC1. The following compiles:
import java.util.*;
public class C1 implements Iterable<C1.NC1> {
private LinkedList<NC1> list;
public static class NC1 {
}
public Iterator<C1.NC1> iterator() {
return list.iterator();
}
}
Alternatively, you could import static yourpackage.C1.NC1.
this code compiles just fine:
public class C1 implements Iterable<NC1> {
public static class NC1 {
}
private LinkedList<NC1> list;
public Iterator<NC1> iterator() {
return this.list.iterator();
}
}
, so there must be an error in a part you omitted
EDIT:
after seeing the other answer:
yes, I have auto-imports switched on, so you need this line:
import com.yourpackage.C1.NC1;
I had an interface initially as below.
public interface testMe {
public Set<String> doSomething();
}
public class A implements testMe {
public Set<String> doSomething() {
return // Set<String>
}
}
I had similar classes implementing testMe. Now I have to add one more class which returns Set<Some Object>
public class X implements testMe() {
public Set<Some OBject> doSomething() {
}
}
How could i add this method in the interface without breaking existing classes?
You can use
public interface testMe {
public Set<?> doSomething();
}
Or
public interface testMe {
public Set<? extends CommonSuperclass> doSomething();
}
You can't for two reasons.
A class or interface can't have two or more methods that have the same number and type of parameters with the same name but differing return types; and
Because of type erasure, all Set<...> instances are, at runtime, simply Set, so they would have the exact same return type anyway.
You will need to name the second something different.
The more complicated answer is that you can make the parameter type extensible:
public interface TestMe<T extends Serializable> {
Set<T> doSomething();
}
public class A implements TestMe<String> {
#Override
public Set<String> doSomething() { ... }
}
public class X implements TestMe<ASerializableObject> {
#Override
public Set<ASerializableObject> doSomething() { ... }
}
I don't believe you can, because type erasure will ruin the effect you have in mind.
You can parameterize the interface:
import java.util.Set;
public interface ISomething<T>
{
Set<T> doSomething(T [] data);
}
And the implementation:
import java.util.HashSet;
import java.util.Set;
public class Something<T> implements ISomething<T>
{
public static void main(String[] args)
{
Something<String> something = new Something<String>();
Set<String> set = something.doSomething(args);
System.out.println(set);
}
public Set<T> doSomething(T [] data)
{
Set<T> foo = new HashSet<T>();
for (T x : data)
{
foo.add(x);
}
return foo;
}
}
I'm not sure this accomplishes what you have in mind, though.