String compareTo
hello SDN community,
Im new here, if im in the wrong forum for my doubt i say sry in advance.
I have a problem with the method compareTo from String.
Example:
publicclass Manager{
private LinkedList<String> list_players =new LinkedList<String>();
public Manager(){
list_players.add("[TDM]High Mage");
list_players.add("[TDM]Red Warrior");
list_players.add("[GoD]Zeyta");
list_players.add("Shaman hp");
list_players.add("[GoD]Publisher");
list_players.add("[TDM]Clarky");
list_players.add("Zasamel");
}
publicvoid orderListByName(){
String aux =null;
for(String i: list_players){
for(String j: list_players){
if(i.compareTo(j) < 0){
aux = i;
i = j;
j = aux;
}
}
}
}
publicvoid showList(){
String aux ="";
for(String s: list_players){
aux += s +"\n";
}
System.out.println(aux);
}
publicstaticvoid main(String[] args){
Manager m =new Manager();
m.showList();
}
}
I have this code here, and wat it shows in the showList() method is this:
[TDM]High Mage
[TDM]Red Warrior
[GoD]Zeyta
Shaman hp
[GoD]Publisher
[TDM]Clarky
Zasamel
My question: Why the names arent ordered? Am i doing a mistake? The only thing i think its wrong its prolly the ASCII code for the "[" or the pointers.
I think theres actually a better way to order this.
[2833 byte] By [
HighMagea] at [2007-11-27 10:10:04]

do you call "orderListByName" anywhere?
ooops my mistake, ill send the right one
public class Manager {
private LinkedList<String> list_players = new LinkedList<String>();
public Manager(){
list_players.add("[TDM]High Mage");
list_players.add("[TDM]Red Warrior");
list_players.add("[GoD]Zeyta");
list_players.add("Shaman hp");
list_players.add("[GoD]Publisher");
list_players.add("[TDM]Clarky");
list_players.add("Zasamel");
}
public void orderListByName(){
String aux = null;
for(String i: list_players){
for(String j: list_players){
if(i.compareTo(j) < 0){
aux = i;
i = j;
j = aux;
}
}
}
}
public void showList(){
orderListByName();
String aux = "";
for(String s: list_players){
aux += s + "\n";
}
System.out.println(aux);
}
public static void main(String[] args){
Manager m = new Manager();
m.showList();
}
}
Result in console:
[TDM]High Mage
[TDM]Red Warrior
[GoD]Zeyta
Shaman hp
[GoD]Publisher
[TDM]Clarky
Zasamel
You realise that all you are doing is changing what Strings the variables i and j are referencing. You don't alter the list in any way.
> You realise that all you are doing is changing what
> Strings the variables i and j are referencing. You
> don't alter the list in any way.
just noticed that :(
could always to an array sort method...
public void secondOrder()
{
String[] strList = list_players.toArray(new String[list_players.size()]);
Arrays.sort(strList);
for (int i = 0; i < strList.length; i++)
{
System.out.println(strList[i]);
}
}
Your orderListByName() method doesn't do anything! Well, OK it does something. This is what it does:
* Declares three variables: aux, i and j
* Assigns lots of different values to these variables
* Returns
It is important to realise that once once the method returns those variables are inaccessible and their (final) values have no impact on the rest of the program. And even more important to realise that assigning values to these variables has absolutely no effect on the contents of list_players.
After all why should assigning a value to a variable you have just declared have an effect on one you declared earlier? Regarding orderListByName(), Shakespeare's description of something "full of sound and fury, signifying nothing" springs to mind.
If you want orderListByName() to alter the list_players list, it will have to call some methods of list_players: get(i) to get the String at position i, and set(i,str) to set it to a new value. The loops will now use a list index.
(Because this is such a common thing to want to do, the Java Collections class has a static sort() method that lets you sort a list like list_players.)
With Collections.sort() works but my real program doesn't use the Object "String" but an Object "Player" and in that class i cant make a compareTo because tht class doesnt control the tags (the tags are the [TDM] and the [GoD]).
So i thought on making an algorithm for arraging the array..but it seems it doesn't work, though i didnt understand quite well what you refered about the orderListByName() not doing anything.
Write your own Comparator and use the Collections.sort method that takes a second parameter.
Ooooh i understood wat u guys meant, ill try wat petes1234 said and see wat happens, thanks for the support
Why? That's extra work you don't need to do.
You mean making an Interface named Comparator with the compareTo method in it?
Sorta, you write a class that implements Comparator.
ok ill show u guys the real thing, im not sure if im understanding wat u guys are saying or if its u guys tht arent understanding, i have a class called Player here:
public class Player {
private int id = 0;
private String name;
private int clan_id = 0;
private static int next_id = 1;
protected Player(String name, int clan_id){
this.id = next_id;
this.name = name;
this.clan_id = clan_id;
next_id++;
}
public Player(Player p){
this.id = p.id;
this.name = p.name;
this.clan_id = p.clan_id;
}
public boolean equals(Object o){
assert o instanceof Player;
Player p = (Player)o;
if(name.equals(p.name)){
return true;
}
return false;
}
public String toString(){
return id + " - " + name + " - " + clan_id;
}
}
And i have a class Clan
public class Clan {
private int id = 0;
private String clan_name;
private String tag;
private static int next_id = 1;
protected Clan(String clan_name, String tag){
assert clan_name != null && tag != null;
this.id = next_id;
this.clan_name = clan_name;
this.tag = tag;
next_id++;
}
public boolean equals(Object o){
assert getClass().equals(o.getClass());
Clan c = (Clan)o;
if(clan_name.equals(c.clan_name) && tag.equals(c.tag)){
return true;
}
return false;
}
public String toString(){
return id + " - " + clan_name + " - " + tag;
}
To summarize:
The Clan class gives the tags to the players with the clan_id linking to clans (in another Manager class), if i do the compareTo in the Player class the tags wont be there, any suggestions?
JavaWorld have an article discussing this: http://www.javaworld.com/javaworld/jw-12-2002/jw-1227-sort.html
Yeah im pretty familiar with using Comparable, why my post in the 2nd from below? :s
> why my post in the 2nd from below?Because the forums are shit!
> you write a class that implements Comparator.Note that because of the way you have implemented equals() in Player you run the risk of ending up with a comparator that is inconsistent with equals - for instance two players with the same name, but in different clans.
Yeah, thts why i cant do a compareTo there, i just want to find a way to have a player with the tag like [TDM]High Mage and then sort all the players, including the clanless ones (the ones tht dont have a tag).
example:
In PlayerManager i have something like this:
private void orderListByName(LinkedList<Player> list_players) throws ClanMessageError{
Player aux = null;
for(Player i: list_players){
for(Player j: list_players){
//here it organizes the clan players
if(i.getClanId() != 0 && j.getClanId() != 0){
String tag = clan_manager.findClan(i.getClanId()).getTag();
String tag2 = clan_manager.findClan(j.getClanId()).getTag();
String name = "[" + tag + "]" + i.getName();
String name2 = "[" + tag2 + "]" + j.getName();
if(name.compareTo(name2) < 0){
aux = new Player(i);
i = j;
j = aux;
}
}
//here it organizes with the clanless players
if(i.getClanId() == 0 && j.getClanId() == 0){
if(i.getName().compareTo(j.getName()) < 0){
aux = new Player(i);
i = j;
j = aux;
}
}
}
}
}
ok in ClanManager theres a list of clans with their clan ids, the findClan returns a clan with the given clan_id as an argument.
I just want the players with the tags (clan players) to be 1st and then the clanless ones next ordered by name, i just cant find a way to fix this :s
This gives the same result as in the last posts i gave
It seems to me that you have to make a Player class that implements the comparable interface, has a name and clan field and that the clan should be an enum: Clan. A playerList class then could sort itself based on the Player compareTo method. This could be implemented like so:
Clan enum:
public enum Clan
{
NO_CLAN, // default value instead of null
TDM,
GoD;
}
PLayer class:
public class Player implements Comparable<Player>
{
private String name;
private Clan clan;
public Player(String name, Clan clan)
{
this.name = name;
this.clan = clan;
}
public Player(String name)
{
this.name = name;
this.clan = Clan.NO_CLAN; // default
}
public String getName()
{
return this.name;
}
public Clan getClan()
{
return this.clan;
}
public void setClan(Clan clan)
{
this.clan = clan;
}
@Override
public String toString()
{
String result = "";
if (clan == Clan.NO_CLAN)
{
result = name;
}
else
{
result = "[" + clan.toString() + "]" + name;
}
return result;
}
public int compareTo(Player p2)
{
if (p2 == null)
{
return 1; // other class is null
}
else if (this.clan == Clan.NO_CLAN && p2.clan != Clan.NO_CLAN)
{
return -1; // other class has a clan, I don't
}
else if (this.clan != Clan.NO_CLAN && p2.clan == Clan.NO_CLAN)
{
return 1; // I have a clan, other class doesn't
}
else if (this.clan.compareTo(p2.clan) != 0)
{
// both have clans and clans different, then compare clans first
return this.clan.compareTo(p2.clan);
}
else
{
// clans same, compare names
return this.name.compareTo(p2.name);
}
}
}
PlayerList class:
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class PlayerList
{
private List<Player> players;
public PlayerList()
{
players = new LinkedList<Player>();
}
public boolean add(Player p)
{
return players.add(p);
}
public boolean remove(Player p)
{
return players.remove(p);
}
public void sort()
{
Collections.sort(players);
}
public void display()
{
for (Iterator iter = players.iterator(); iter.hasNext();)
{
Player p = (Player) iter.next();
System.out.println(p);
}
}
}
TestPlayerList class:
public class TestPlayerList
{
private PlayerList players;
public TestPlayerList()
{
players = new PlayerList();
players.add(new Player("High Mage", Clan.TDM));
players.add(new Player("Red Warrior", Clan.TDM));
players.add(new Player("Zeyta", Clan.GoD));
players.add(new Player("Shaman hp"));
players.add(new Player("Publisher", Clan.GoD));
players.add(new Player("Clarky", Clan.TDM));
players.add(new Player("Zasamel"));
}
public void display()
{
players.display();
}
public void sort()
{
players.sort();
}
public static void main(String[] args)
{
TestPlayerList tc = new TestPlayerList();
tc.display();
System.out.println();
tc.sort();
tc.display();
}
}
also, why a linked list rather than an array list?
Well so i learnt that a LinkedList has his element and has a pointer to the next, saving memory, while in an ArrayList, it reserves memory space and if tht space is full he reserves even more memory space, leaving some empty memory tht could be used elsewhere. Dunno if the ArrayList is good for something else?
In the resolution u told me, the Clan enum has to be a class, because i also save the String name of the clan, not only the tag, but ill try doing it without being an enum, thx for ur help :)
Also, im reading a file "clans.txt" with the constructor "public Clan(Scanner f)", meaning i cant use the enum. Also.. if u guys have a better way and use a DataBase program like MySQL and point me the basics on how to read it i would appreciate it..i think reading from txt files kinda primitive :s
> Well so i learnt that a LinkedList has his element
> and has a pointer to the next, saving memory, while
> in an ArrayList, it reserves memory space and if tht
> space is full he reserves even more memory space,
> leaving some empty memory tht could be used
> elsewhere. Dunno if the ArrayList is good for
> something else?
I think (and I could be wrong), that ArrayList is better at random access than LinkedList... but my expertice in this is very sketchy (read: none). I do recommend that you consider declaring the variable as List, then I believe you can go either way with the List's implementation.
> In the resolution u told me, the Clan enum has to be
> a class, because i also save the String name of the
> clan, not only the tag, but ill try doing it without
> being an enum, thx for ur help :)
> Also, im reading a file "clans.txt" with the
> constructor "public Clan(Scanner f)", meaning i cant
> use the enum.
Enum can handle objects that hold multiple variables including String, but you are right; if Clan is not fixed but something that needs to be read in from a file, you can't use Enum (again, "I think").
> Also.. if u guys have a better way and
> use a DataBase program like MySQL and point me the
> basics on how to read it i would appreciate it..i
> think reading from txt files kinda primitive :s
Yeah, databases could be the way to go. I bet if you google:
MySQL tutorial java
you'll get lots of useful hits.
Good luck!
hmm I think its not possible to do wat u guys want me to do, i better just show u all :|
public class Clan {
private int id = 0;
private String clan_name;
private String tag;
private static int next_id = 1;
protected Clan(String clan_name, String tag){
this.id = next_id;
this.clan_name = clan_name;
this.tag = tag;
next_id++;
}
protected Clan(Scanner f) throws TXTException{
if(f.hasNextInt()){
this.id = f.nextInt();
next_id = id;
}
if(f.hasNext("-")){
f.next();
String clan = "";
while(!f.hasNext("-")){
clan += f.next() + " ";
}
clan = clan.trim();
this.clan_name = clan;
}
if(f.hasNext("-")){
f.next();
this.tag = f.next();
}
next_id++;
}
}
public class ClanManager {
private LinkedList<Clan> list_clans = new LinkedList<Clan>();
public ClanManager() throws TXTException{
try{
Scanner f = new Scanner(new File("files/clans.txt"));
while(f.hasNextInt()){
list_clans.add(new Clan(f));
}
if(f.hasNext()){//if theres something else to read, tht means the file was red badly
f.close();
throw new TXTException("Theres some problems with the syntax in the file, " +
"check if u seperate all the IDs, CLAN NAMEs and TAGs with a '-'", "Clan");
}
f.close();
}catch(FileNotFoundException e){
JOptionPane.showMessageDialog(null, e.toString());
}
}
public Clan findClan(int id) throws ClanMessageError{
for(Clan c: list_clans){
if(c.getClanId() == id){
return c;
}
}
throw new ClanMessageError("" + id, "No");
}
}
public class Player {
private int id = 0;
private String name;
private int clan_id = 0;
private static int next_id = 1;
protected Player(String name, int clan_id){
this.id = next_id;
this.name = name;
this.clan_id = clan_id;
next_id++;
}
protected Player(Scanner f) throws TXTException{
if(f.hasNextInt()){
this.id = f.nextInt();
}
if(f.hasNext("-")){
f.next();
String player = "";
while(!f.hasNext("-")){
player += f.next() + " ";
}
player = player.trim();
this.name = player;
}
if(f.hasNext("-")){
f.next();
if(f.hasNextInt()){
this.clan_id = f.nextInt();
}
}
checkPlayer();
next_id++;
}
}
public class PlayerManager {
private ClanManager clan_manager;
private LinkedList<Player> list_players = new LinkedList<Player>();
private boolean with_tags = true;
public PlayerManager(){
try{
this.clan_manager = new ClanManager();
Scanner f = new Scanner(new File("files/players.txt"));
while(f.hasNextInt()){
list_players.add(new Player(f));
}
}catch(FileNotFoundException e){
JOptionPane.showMessageDialog(null, "file \"players.txt\" cant be found");
}catch(TXTException e){
JOptionPane.showMessageDialog(null, e.toString());
}
}
private void orderListByName(LinkedList<Player> list_players) throws ClanMessageError{
//wat to put here?
}
}
i had the CompareTo in the Player class before, but wat id did was organize the players by their name and WITHOUT the tag. I want it to order it WITH the tags. Im sry if im giving u guys too much trouble but im really getting frustrated with this :(
I don't know what use you are putting these id's to, so maybe it would be easier for a Player to have a Clan member rather than an int id.
But, however you organise these classes the implementation of orderListByName() will have to follow one of the methods suggested above:
Either -
Write a Comparator<Person> and use Collections.sort() to sort the list
Or -
Do the sort yourself as you were before but use the List methods get() and set() so that the list actually gets sorted.
Forgive me if I'm mistaken, but I wonder if the original problem (list being effectively sorted), has been clarified. Perhaps this might help:import java.util.ArrayList;
import java.util.List;
public class ChangingListEg {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("first");
list.add("second");
list.add("third");
System.out.println("Original:" + list);
testOne(list);
System.out.println("After test 1: " + list);
testTwo(list);
System.out.println("After test 2: " + list);
}
static void testOne(List<String> data) {
for(String str: data) {
str = str + " CHANGED!";
}
}
static void testTwo(List<String> data) {
for(int ndx = 0; ndx < data.size(); ndx++) {
String str = data.get(ndx);
str = str + " CHANGED!";
data.set(ndx, str);
}
}
}
Well if i am going to make my own sort, how do u suggest to do it? The BubbleSort method is the only way i know (the way i did tht doesnt change a thing)And u mean to override the sort from Collections? if so i dunno how to do it..only know how to override methods from class Object.
> The BubbleSort method is the only way i know (the way i did tht doesnt change a
> thing)
A bubble sort will be effective. Change the way you implemented it. (reply 24)
> And u mean to override the sort from Collections?
No. I meant write the comparator, then invoke sort(). (replies 13 and 14)
List is a superclass of ArrayList and LinkedList? Wats the difference between the List and LinkedList? :s
I tested tht code u showed me, so if i use a for each i cant change the order of the list? i have to acess it threw Indexes to change the order? :s
> List is a superclass of ArrayList and LinkedList?
Close. List is an interface that ArrayList, LinkedList and lots of other classes implement. An interface is a description of the sorts of things an object promises to be able to do - it describes what, not how. In the case of List this promise includes having get() and set() methods that allow you to look at and change list elements.
ArrayList, LinkedList and all the other classes that implement List live up to this promise by having get() and set() methods. It's very common for variables to be declared using an interface rather than a specific class. (This was referred to earlier in the thread, along with the suggestion that you do that.)
> Wats the difference between the List and LinkedList?
A LinkedList is a sort of List. The same way that an apple is a sort of fruit. So is a grape.
Small children sometimes have a difficulty with this. "I wanna Fruit. An Apple? No, a Fruit!" At some time in the past they have pointed to a grape and asked some other adult "what that is" and been told that it's a sort of fruit. They didn't grasp the significance of "sort of" and it's ... fruitless ... trying to explain it to them. "Well, there are all sorts of types of fruit..." They know when they're being talked out of something: "Nooo! A Fruit!"
They quickly learn the specific names for the specific things they want. Only later - when they have to pay for the stuff - do they realise that to some extent apples, grapes and the rest are interchangable. Depending on season, price and so forth you eat the most appropriate fruit implementation.
> I tested tht code u showed me, so if i use a for each i cant change the order of the
> list? i have to acess it threw Indexes to change the order?
Try rewriting your bubble sort and see.
By the way, you don't need to use the "copy constructor" to make aux. Instead the code will look something like (ie don't copy and paste)for(int i = 0, i < list_players.size; i++){
for(int j = 0; j < list_players.size(); j++) {
Player first = list_players.get(i);
Player second = list_players.get(j);
if(first.compareTo(second) < 0) {
list_players.set(i, second);
list_players.set(j, first);
}
}
}
really nice explained, thx :) didnt know i could use Objects tht belonged to Interfaces? And why not make it LinkedList instead of only a List? Also, using the TestOne method is not advisable to order the List, only TestTwo? Im really getting confused here..shouldnt the results be the same on both tests? :s
> And why not make it LinkedList instead of only a List?
Because you only need the methods it promises as a List - get() and set(). I would ask this question the other way around. "Why limit your choices to a LinkedList when any List will do?"
Google - or search this forum - for the different properties of the different list implementations. (Or just read the posts - It gets asked here about once a week, so you won't have to wait long for an answer.) At this stage the point is that it really doesn't matter. So long as you declare and use it as a List you can change it later by changing a single line (the one near the top of PlayerManager)//private List<Player> list_players = new LinkedList<Player>();
// found this was better
private List<Player> list_players = new ArrayList<Player>();
> Im really getting confused here..shouldnt the results be the same on both tests?
No. What is the same about both tests is that they both give you references to the list elements - str. This is fine if what you want to do is change the list elements themselves (call methods of the list elements etc).
But if you want to change the list (rather than its elements) you need more than references to its elements. The second test is effective because it works using a list index which can be used with the List methods get() and set() to change the list itself.
Wow didnt know tht thx :) its working now (Finnally :D)
So u suggest i make all my LinkedList to ArrayList? Well its just my college teacher used to do with LinkedList and he said it was better as i replied above (thts wat he told me). Meanwhile ill do some research :)
And another thing, why cant i copy paste? (its not as if i did it ill prove to u i didnt)
private void orderListByName(LinkedList<Player> list_players) throws ClanMessageError{
for(int i = 0 ; i < list_players.size() ; ++i){
for(int j = 0 ; j < list_players.size() ; ++j){
String tag;
String tag2;
String name;
String name2;
if(with_tags){
if(list_players.get(i).getClanId() != 0){
tag = clan_manager.findClan(list_players.get(i).getClanId()).getTag();
name = "[" + tag + "]" + list_players.get(i).getName();
}else{
name = list_players.get(i).getName();
}
if(list_players.get(j).getClanId() != 0){
tag2 = clan_manager.findClan(list_players.get(j).getClanId()).getTag();
name2 = "[" + tag2 + "]" + list_players.get(j).getName();
}else{
name2 = list_players.get(j).getName();
}
}else{
name = list_players.get(i).getName();
name2 = list_players.get(j).getName();
}
Player p1 = list_players.get(i);
Player p2 = list_players.get(j);
if(name.compareTo(name2) < 0){
list_players.set(i, p2);
list_players.set(j, p1);
}
}
}
}
> Wow didnt know tht thx :) its working now (Finnally :D)
Excellent!
> So u suggest i make all my LinkedList to ArrayList?
No! Which implementation of List you use depends on other things, they all function OK as lists. Whether apples or grapes are appropriate depends (to the world weary adult, at least) on season, price and other aspects of circumstance.
> Meanwhile ill do some research :)
Exactly.
> And another thing, why cant i copy paste?
Only because I'm quite likely to fcuk it up. (Did the first time, too - had j for i).
Oh sry i thought u didnt want me to copy paste because of author rights or because i wouldnt learn that way :s