What is the best Collection for this?
I have a class Person
with a String name and an int age.
Code:
Public Class Person implements comparable<String>
{
public final String name
public final int age
...
... lots of constructors and methods
}
where comparable is just sorting over the name. (all persons have a name, and all persons have a different name)
And I want to put/ add some Perons in a sorted collection.
and want to be able
- to test if some string is a name of a person in the collection
- if it is the name is of a person , get his age and other info from the person
- to be able to iterate alphabethicly by the name over the Collection
at the moment I do it with a TreeMap<String, Person> map
(where the String is the name of the person, and Person the complete Person Object)
but that does not allow to iterate over the collection (I first need to copy the map to a set with map.values() )
It works but i am not really happy with it and cannot stop wondering is this really nescessary to use TreeMap, is it not possible to do it with TreeSet or another sorted collection?
Re: What is the best Collection for this?
Quote:
Originally Posted by
willemien
I have a class Person
with a String name and an int age.
Code:
Public Class Person implements comparable<String>
{
public final String name
public final int age
...
... lots of constructors and methods
}
where comparable is just sorting over the name. (all persons have a name, and all persons have a different name)
Your code has a coding (compiler) error and a logic error. The class should implement the Comparable interface, not the comparable one which doesn't exist. If this seems picky to you, so be it, but I'm being no more picky than the Java compiler, and because of this, you should strive for accuracy when posting code here. Next it should implement the Comparable<Person> interface, not Comparable<String>. Even if it will be the Strings that will be compared in the compareTo method, you are still in essence comparing one Person to another, and it is another Person that you want to have passed into the compareTo method, not a String. You will extract the other Person's String in that method, not to worry, but still a Person needs to be passed into the method for the interface to work correctly at all.
Quote:
And I want to put/ add some Perons in a sorted collection.
and want to be able
- to test if some string is a name of a person in the collection
- if it is the name is of a person , get his age and other info from the person
- to be able to iterate alphabethicly by the name over the Collection
at the moment I do it with a TreeMap<String, Person> map
(where the String is the name of the person, and Person the complete Person Object)
but that does not allow to iterate over the collection (I first need to copy the map to a set with map.values() )
Yes it allows iteration over the map by simply extracting all the values from the map as a set. If you check the TreeMap API, you'll see that the keySet() method returns a set of the key values sorted in ascending order. It's a trivial business to extract the Person of interest when doing this iteration.
Quote:
It works but i am not really happy with it and cannot stop wondering is this really nescessary to use TreeMap, is it not possible to do it with TreeSet or another sorted collection?
You could do what you with with a TreeSet or with a simple ArrayList that has been sorted using Collections.sort(...).
Re: What is the best Collection for this?
Thanks for your reply
Sorry I tried to keep it to simple
The classes I have are (still much simplified, the real classes are a couple of hundreds lines long )
Code:
// main Classes
Public Class Simple
implements Comparable<Simple>
{
private final String name;
//Constructor
public Simple (String inName){
name = inName
}
public int compareTo(Simple simple){
int diff = this.length() - simple.length();
if (diff != 0) return diff;
return name.compareTo(simple.toString());
}
public int hashCode(){
return name.hashCode();
}
public int lenght(){
return name.length();
}
public String toString(){
return name;
}
// lots of other methods(around 30)
}
// extended Class
Public Class Complex extends Simple
implements Comparable<Simple> // <-- not sure if this is needed
{
private int score;
// some other fields still in development
...
Complex (String name, int inScore){
super(name)
score = inScore;
}
getScore(){
return score;
}
// lots of other methods(another 50)
}
// Collection Class for Complex (is a Singleton)
Class ComplexList
{
private collection
// methods
public synchronised addComplex(Complex){
// code to add a Complex to collection
// every Complex has a different name/Simple
}
public boolean test(Simple test){
// code to test if there is a Complex with name of Simple
}
public Complex getComplex(Simple name){
// code to get the Complex with name
}
public synchronised String[] getNameArray(){
// code to get Array of names, sorted by length, name
// not used very often
}
// some other methods
}
My question is now what is the best collection to use in ComplexList,
at the moment it is:
Code:
TreeMap<Simple, Complex) map
and methods are:
public synchronised addComplex(Complex newComplex){
Simple newSimple = newComplex; //auto downcasting
map.put(newSimple, newComplex);
}
public Complex getComplex(Simple name){
// some tests (not every simple is a Complex)
return map.get(name)
}
public synchronised String[] getNameArray(){
Simple[] simpleArray = map.keySet().toArray(new String[0]);
int len = nameArray.length;
String[] nameArray = new String[len];
for (int i =0 ; i < len ; i++ ){
nameArray[i] = simpleArray[i].toString();
}
return stringArray;
}
I am not sure how to do it with a TreeSet, especially how do I code getComplex(Simple name) to get the ComplexObject out of the collection?
More info:
The collection can grow quite big (say around 50 000 till 500 000 entries)
and especially adding and testing needs to be done efficient.
The getComplex() and getNameArray() methods are not used often, (the getComplex() more often than the getNameArray()) so they don't need to be very efficient, also at the moment getNameArray() makes two arrays (simpleArray and nameArray) can it be done by making only one (nameArray)?
Hope this makes it all clearer
Re: What is the best Collection for this?
I think you might need a better example, as currently Simple is a pointless class as it is simply a String.
If that is the case with your code then ditch the Simple and go for a Map<String, Complex>.
Complex does not need to be Comparable as you don't need to order it.
Is the idea to be able to get the Complex object based on aomething like a String value in the object?
Re: What is the best Collection for this?
Quote:
Originally Posted by
Tolls
I think you might need a better example, as currently Simple is a pointless class as it is simply a String.
If that is the case with your code then ditch the Simple and go for a Map<String, Complex>.
Complex does not need to be Comparable as you don't need to order it.
Is the idea to be able to get the Complex object based on aomething like a String value in the object?
The Class Simple has lots of other methods as well, it is true that its only field is a final string , but it is not just a string :) (it is in fact a logical formula in Polish notation)
the Complex Class is a special kind of formula (a proved canonical fomula) and has some other (mutable) private fields besides its fomula, and I need to be able to get to the ComplexObject itself to use its methods (Complex has methods that let me use and manipulate these fields) to reach them.
simply upcasting Simple to an Complex won't work.
Also the ordering of Simple is not the normal String ordering, but I thought that I could use the normal String hashcode because equal fomulas have equal names.
I guess describing the rest would i guess be superfluos (but do send me a pm if you want to learn abstract level non-classical symbolic logic)
Re: What is the best Collection for this?
OK.
I think we've seen something similar here a few years ago (though not about how to collect these things).
Based on your criteria in the OP (ordered by the String, access based on the Simple class) then TreeMap<Simple, Complex>.
However if you really just want to get at the Complex via the String then TreeMap<String, Complex> and provide your own Comparator to handle your special ordering requirements.
Re: What is the best Collection for this?
Quote:
Originally Posted by
Tolls
OK.
I think we've seen something similar here a few years ago (though not about how to collect these things).
Based on your criteria in the OP (ordered by the String, access based on the Simple class) then TreeMap<Simple, Complex>.
However if you really just want to get at the Complex via the String then TreeMap<String, Complex> and provide your own Comparator to handle your special ordering requirements.
Thanks
I do prefer to access the ComplexObject via a SimpleObject, but I don't really care, converting a SimpleObject to a String is i guess very efficient (test are more in the traject in testing if a String is a valid SimpleObject i
I will l keep it as a TreeMap, I just hoped i could do it with a TreeSet or other collection instead.
Also can you give me suggestions on how to improve the getNameArray() method so that it only uses one array instead of two.
Re: What is the best Collection for this?
A Set makes no sense if you wante to access these things via a particular name.
You'd need to write the mapping code for that, and that says "use a Map" to me.
For the array just iterate over the keySet:
Code:
String[] nameArray = new String[map.keySet().size()];
int i = 0;
for (Simple s : map.keySet()) {
nameArray[i] = s.getName();
i++;
}
There may be a quicker way, but that'll get you what you need.
It's iterating over the keySet. No point turning that into an array.
Re: What is the best Collection for this?