Сортировка в Hash Maps - PullRequest
       22

Сортировка в Hash Maps

1 голос
/ 15 мая 2010

Я пытаюсь познакомиться с коллекциями. У меня есть строка, которая является моим ключом, адресом электронной почты и объектом Person (firstName, lastName, телефон, электронная почта). В главе о коллекциях Java на веб-страницах Sun я прочитал, что если у вас есть HashMap и вы хотите его отсортировать, вы можете использовать TreeMap. Как работает этот вид? Он основан на методе CompareTo (), который есть в вашем классе Person? Я переопределил метод CompareTo () в моем классе Person для сортировки по lastName. Но это не работает должным образом, и мне было интересно, есть ли у меня правильная идея или нет. getSortedListByLastName в нижней части этого кода, где я пытаюсь преобразовать в TreeMap. Кроме того, если это правильный способ сделать это или один из правильных способов сделать это, как мне тогда выполнить сортировку по firstName, так как мой compareTo () сравнивает по lastName.

import java.util.*;

public class OrganizeThis 
{
    /** 
    Add a person to the organizer

    @param p A person object
    */
    public void add(Person p)
    {   
        staff.put(p.getEmail(), p);
        //System.out.println("Person " + p + "added");
    }

    /**
    * Remove a Person from the organizer.
    *
    * @param email The email of the person to be removed.
    */
    public void remove(String email)
    {
        staff.remove(email);
    }

    /**
    * Remove all contacts from the organizer.
    *
    */
    public void empty()
    {
        staff.clear();
    }

    /**
    * Find the person stored in the organizer with the email address.
    * Note, each person will have a unique email address.
    * 
    * @param email The person email address you are looking for.
    *
    */
    public Person findByEmail(String email)
    {
        Person aPerson = staff.get(email);
        return aPerson;
    }

    /**
    * Find all persons stored in the organizer with the same last name.
    * Note, there can be multiple persons with the same last name.
    * 
    * @param lastName The last name of the persons your are looking for.
    *
    */
    public Person[] find(String lastName)
    {
        ArrayList<Person> names = new ArrayList<Person>();

        for (Person s : staff.values())
        {
            if (s.getLastName() == lastName) {
                names.add(s);
            }
        }
        // Convert ArrayList back to Array
        Person nameArray[] = new Person[names.size()];
        names.toArray(nameArray);
        return nameArray;
    }

    /**
    * Return all the contact from the orgnizer in
    * an array sorted by last name.
    * 
    * @return An array of Person objects.
    *
    */
    public Person[] getSortedListByLastName()
    {
        Map<String, Person> sorted = new TreeMap<String, Person>(staff);
        ArrayList<Person> sortedArrayList = new ArrayList<Person>();
        for (Person s: sorted.values()) {
            sortedArrayList.add(s);
        }
        Person sortedArray[] = new Person[sortedArrayList.size()];
        sortedArrayList.toArray(sortedArray);
        return sortedArray;
    }

    private Map<String, Person> staff = new HashMap<String, Person>();

public static void main(String[] args)
    {
        OrganizeThis testObj = new OrganizeThis();
        Person person1 = new Person("J", "W", "111-222-3333", "JW@ucsd.edu");
        Person person2 = new Person("K", "W", "345-678-9999", "KW@ucsd.edu");
        Person person3 = new Person("Phoebe", "Wang", "322-111-3333", "phoebe@ucsd.edu");
        Person person4 = new Person("Nermal", "Johnson", "322-342-5555", "nermal@ucsd.edu");
        Person person5 = new Person("Apple", "Banana", "123-456-1111", "apple@ucsd.edu");
        testObj.add(person1);
        testObj.add(person2);
        testObj.add(person3);
        testObj.add(person4);
        testObj.add(person5);

        System.out.println(testObj.findByEmail("JW@ucsd.edu"));
        System.out.println("------------" + '\n');

        Person a[] = testObj.find("W");

        for (Person p : a)
        System.out.println(p);

        System.out.println("------------" + '\n');
        a = testObj.find("W");

        for (Person p : a)
        System.out.println(p);

        System.out.println("SORTED" + '\n');
        a = testObj.getSortedListByLastName();
        for (Person b : a) {
            System.out.println(b);
        }
    }
    }

Класс человека:

public class Person implements Comparable
{
    String firstName;
    String lastName;
    String telephone;
    String email;

    public Person()
    {
       firstName = "";
       lastName = "";
       telephone = "";
       email = "";
    }

    public Person(String firstName)
    {
        this.firstName = firstName;
    }

    public Person(String firstName, String lastName, String telephone, String email) 
    {
        this.firstName = firstName;
        this.lastName = lastName;
        this.telephone = telephone;
        this.email = email;
    }

    public String getFirstName()
    {
        return firstName;
    }

    public void setFirstName(String firstName)
    {
        this.firstName = firstName;
    }

    public String getLastName()
    {
        return lastName;
    }

    public void setLastName(String lastName)
    {
        this.lastName = lastName;
    }

    public String getTelephone()
    {
        return telephone;
    }

    public void setTelephone(String telephone)
    {
        this.telephone = telephone;
    }

    public String getEmail()
    {
        return email;
    }

    public void setEmail(String email)
    {
        this.email = email;
    }

    public int compareTo(Object o)
    {
        String s1 = this.lastName + this.firstName;
        String s2 = ((Person) o).lastName + ((Person) o).firstName;
        return s1.compareTo(s2);
    }

    public boolean equals(Object otherObject)
    {
        // a quick test to see if the objects are identical
        if (this == otherObject) {
            return true;
        }

        // must return false if the explicit parameter is null
        if (otherObject == null) {
            return false;
        }

        if (!(otherObject instanceof Person)) {
            return false;
        }

        Person other = (Person) otherObject;
        return firstName.equals(other.firstName) && lastName.equals(other.lastName) &&
            telephone.equals(other.telephone) && email.equals(other.email);
    }

    public int hashCode() 
    {
        return this.email.toLowerCase().hashCode();
    }

    public String toString()
    {
        return getClass().getName() + "[firstName = " + firstName + '\n'
                                    + "lastName = " + lastName + '\n'
                                    + "telephone = " + telephone + '\n'
                                    + "email = " + email + "]";
    }


}

Ответы [ 2 ]

8 голосов
/ 15 мая 2010

На самом деле вы ошибаетесь.

Вот суть:

  • Map<K,V> - это отображение от K key до V value
  • TreeMap<K,V> - это SortedMap<K,V>, который сортирует ключи , а не значения

Таким образом, TreeMap<String,Person> будет сортировать по адресам электронной почты, а не по именам и фамилиям Person.

Если вам нужен SortedSet<Person> или отсортированный List<Person>, тогда это другая концепция, и да, Person implements Comparable<Person> или Comparator<Person> пригодится.

API ссылки

Похожие вопросы


Пример

Уже есть множество примеров, но вот еще один:

import java.util.*;

public class Example {
    static String lastName(String fullName) {
        return fullName.substring(fullName.indexOf(' ') + 1);
    }
    public static void main(String[] args) {
        Map<String,String> map = new TreeMap<String,String>();
        map.put("001", "John Doe");
        map.put("666", "Anti Christ");
        map.put("007", "James Bond");

        System.out.println(map);
        // "{001=John Doe, 007=James Bond, 666=Anti Christ}"
        // Entries are sorted by keys!

        // Now let's make a last name Comparator...
        Comparator<String> lastNameComparator = new Comparator<String>() {
            @Override public int compare(String fullName1, String fullName2) {
                return lastName(fullName1).compareTo(lastName(fullName2));
            }
        };

        // Now let's put all names in a SortedSet...
        SortedSet<String> namesByLastName =
            new TreeSet<String>(lastNameComparator);
        namesByLastName.addAll(map.values());

        System.out.println(namesByLastName);
        // "[James Bond, Anti Christ, John Doe]"
        // Names sorted by last names!

        // Now let's use a List instead...
        List<String> namesList = new ArrayList<String>();
        namesList.addAll(map.values());
        System.out.println(namesList);
        // "[John Doe, James Bond, Anti Christ]"
        // These aren't sorted yet...

        Collections.sort(namesList);
        System.out.println(namesList);
        // "[Anti Christ, James Bond, John Doe]"
        // Sorted by natural ordering!

        // Now let's sort by string lengths...
        Collections.sort(namesList, new Comparator<String>() {
            @Override public int compare(String s1, String s2) {
                return Integer.valueOf(s1.length()).compareTo(s2.length());
            }
        });
        System.out.println(namesList);
        // "[John Doe, James Bond, Anti Christ]"
        // SUCCESS!!!
    }
}
0 голосов
/ 15 мая 2010

Как хорошо объяснили полигенасыщенные смазки, SortedMap сортируется по ключу , а не по значению .

Однако, с помощью LinkedHashMap можно изменить порядок Map так, как вы хотите. LinkedHashMap поддерживает порядок вставки, как List.

Первый шаг - получить пары ключ / значение в структуре сортируемых данных, например, List<Entry<K, V>>, который вы, в свою очередь, сортируете, используя Collections#sort() с помощью Compatator<Entry<K, V>> и, наконец, заполняете им LinkedHashMap (не HashMap, иначе вы потеряете порядок снова). 1023 *

Вот базовый пример (оставляя в стороне очевидную обработку исключений во время выполнения):

// Prepare.
Map<String, String> map = new HashMap<String, String>();
map.put("foo", "bar");
map.put("bar", "waa");
map.put("waa", "foo");
System.out.println(map); // My JVM shows {waa=foo, foo=bar, bar=waa}

// Get entries and sort them.
List<Entry<String, String>> entries = new ArrayList<Entry<String, String>>(map.entrySet());
Collections.sort(entries, new Comparator<Entry<String, String>>() {
    public int compare(Entry<String, String> e1, Entry<String, String> e2) {
        return e1.getValue().compareTo(e2.getValue());
    }
});

// Put entries back in an ordered map.
Map<String, String> orderedMap = new LinkedHashMap<String, String>();
for (Entry<String, String> entry : entries) {
    orderedMap.put(entry.getKey(), entry.getValue());
}

System.out.println(orderedMap); // {foo=bar, waa=foo, bar=waa}

Само собой разумеется, что это, в конце концов, не правильная структура данных для ваших целей;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...