2016-05-01 5 views
0

Вот код treeet объекта, определенного пользователем.Как значение передается в пользовательскую функцию сравнения в treeet

package com.java2novice.treeset; 

import java.util.Comparator; 
import java.util.TreeSet; 

public class MyCompUserDefine { 

    public static void main(String a[]){ 
     //By using name comparator (String comparison) 
     TreeSet<Empl> nameComp = new TreeSet<Empl>(new MyNameComp()); 
     nameComp.add(new Empl("Ram",3000)); 
     nameComp.add(new Empl("John",6000)); 
     nameComp.add(new Empl("Crish",2000)); 
     nameComp.add(new Empl("Tom",2400)); 
     for(Empl e:nameComp){ 
      System.out.println(e); 
     } 
     System.out.println("==========================="); 
     //By using salary comparator (int comparison) 
     TreeSet<Empl> salComp = new TreeSet<Empl>(new MySalaryComp()); 
     salComp.add(new Empl("Ram",3000)); 
     salComp.add(new Empl("John",6000)); 
     salComp.add(new Empl("Crish",2000)); 
     salComp.add(new Empl("Tom",2400)); 
     for(Empl e:salComp){ 
      System.out.println(e); 
     } 
    } 
} 

class MyNameComp implements Comparator<Empl>{ 

    @Override 
    public int compare(Empl e1, Empl e2) { 
     return e1.getName().compareTo(e2.getName()); 
    } 
} 

class MySalaryComp implements Comparator<Empl>{ 

    @Override 
    public int compare(Empl e1, Empl e2) { 
     if(e1.getSalary() > e2.getSalary()){ 
      return 1; 
     } else { 
      return -1; 
     } 
    } 
} 

class Empl{ 

    private String name; 
    private int salary; 

    public Empl(String n, int s){ 
     this.name = n; 
     this.salary = s; 
    } 

    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
    public int getSalary() { 
     return salary; 
    } 
    public void setSalary(int salary) { 
     this.salary = salary; 
    } 
    public String toString(){ 
     return "Name: "+this.name+"-- Salary: "+this.salary; 
    } 
} 

Мой вопрос, когда я звоню MyNameComp() или MySalaryComp(), то я просто звоню его конструктор без прохождения каких-либо значение. Но как передается значение или объект класса EMP1?

ответ

0

TreeSet сохраняет свои элементы отсортированными. Если вы предоставляете компаратор, он использует этот пользовательский компаратор (в вашем случае MyNameComp() или MySalaryComp()) для их сравнения и сортировки. Вам не нужно ничего называть, TreeSet будет обрабатывать его внутренне.

0

Созданные объекты TreeSet ответственны за использование компаратора, который вы передали при его создании.

Как это делает TreeSet, это не должно вас беспокоить, потому что это деталь реализации. TreeSet просто гарантирует, что предоставленный вами компаратор будет использоваться, когда это необходимо. Вам не нужно об этом думать ... но просто для этого, давайте посмотрим на источник (пожалуйста, учтите, что вы не должны полагаться на детали реализации любых классов, поскольку они могут свободно меняться, когда вы используете API , вы можете быть уверены, что это явная часть интерфейса!)

Давайте начнем с TreeSet constructor that takes a Comparator as an argument, это то, что вы звоните, когда вы создаете свои TreeSet экземпляры в приведенных примерах

public More ...TreeSet(Comparator<? super E> comparator) { 
    this(new TreeMap<E,Object>(comparator)); 
} 

Мы видим, что the constructor использует компаратор для создания экземпляра TreeMap вызовов другого конструктора TreeSet. Созданный здесь TreeMap будет использоваться для хранения товаров в TreeSet.

Оставим это, не проверяя, что происходит внутри TreeMap. Нам просто нужно знать, что TreeMap - это то, что на самом деле хранит предметы. Это знание пригодится, когда мы посмотрим, что происходит, когда вы добавляете элементы.

Вы вставляете все элементы, используя TreeSet#add method, который использует ту же карту, которая была создана при вызове конструктора.

public boolean More ...add(E e) { 
    return m.put(e, PRESENT)==null; 
} 

Объект m является TreeMap экземпляра внутри конструктора. Поскольку мы знаем, что это TreeMap и что используется метод put, мы можем посмотреть, что он делает.

Вот реализация TreeMap#put

Этот метод использует компаратор, который при ближайшем рассмотрении, оказывается таким же один, который был использован при создании TreeMap в TreeSet конструктора.

public V More ...put(K key, V value) { 
    Entry<K,V> t = root; 
    if (t == null) { 
     // TBD: 
     // 7: (coll) Adding null to an empty TreeSet should 
     // throw NullPointerException 
     // 
     // compare(key, key); // type check 
     root = new Entry<K,V>(key, value, null); 
     size = 1; 
     modCount++; 
     return null; 
    } 
    int cmp; 
    Entry<K,V> parent; 
    // split comparator and comparable paths 
    Comparator<? super K> cpr = comparator; 
    if (cpr != null) { 
     do { 
      parent = t; 
      cmp = cpr.compare(key, t.key); 
      if (cmp < 0) 
       t = t.left; 
      else if (cmp > 0) 
       t = t.right; 
      else 
       return t.setValue(value); 
     } while (t != null); 
    } 
    else { 
     if (key == null) 
      throw new NullPointerException(); 
     Comparable<? super K> k = (Comparable<? super K>) key; 
     do { 
      parent = t; 
      cmp = k.compareTo(t.key); 
      if (cmp < 0) 
       t = t.left; 
      else if (cmp > 0) 
       t = t.right; 
      else 
       return t.setValue(value); 
     } while (t != null); 
    } 
    Entry<K,V> e = new Entry<K,V>(key, value, parent); 
    if (cmp < 0) 
     parent.left = e; 
    else 
     parent.right = e; 
    fixAfterInsertion(e); 
    size++; 
    modCount++; 
    return null; 
} 

Это немного сложнее, и вы должны прочитать остальную часть реализации, чтобы получить полное представление о том, что здесь происходит, но это ясно видно, что при условии, компаратор привыкает.

Суть здесь, однако, состоит в том, что этот не должен иметь значения для вас или вашего кода как клиент коллекций API. Вы должны полагаться только на то, что явно указано в Javadoc методов public или protected.

Вы можете посмотреть на the JDK 8 version, чтобы увидеть, что внутренние органы изменились (хотя и очень немного)

Причина вы можете быть уверены, что TreeMap и при условии, Comparator будет использоваться, потому что это часть TreeSet ' s API. Цитирую TreeSet Javadoc:

TreeSet есть) NavigableSet реализации, основанный на TreeMap. Элементы упорядочиваются с использованием их естественного упорядочения или Comparator, предоставленных в заданное время создания, в зависимости от того, какой конструктор используется.

Изменение любой из этих вещей приведет к разорению контракта.