如何将值传递到树集

时间:2016-05-01 18:47:12

标签: java treeset

这是用户定义对象的树集代码。

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类的价值或对象是如何传递的?

2 个答案:

答案 0 :(得分:1)

您创建的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插入所有项目,TreeMap#put使用调用构造函数时创建的相同地图。

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

m对象是构造函数中实例化的TreeMap。由于我们知道它是TreeMap并且使用了put方法,因此我们可以看看它的作用。

以下是the JDK 8 version

的实施

此方法使用比较器,经过仔细检查,结果与在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的客户端无关紧要。您应该只依赖于publicprotected方法的Javadoc中明确说明的内容。

你可以看看TreeSet Javadoc,看看内部是否发生了变化(虽然非常轻微)

您可以确定使用TreeMap和提供的Comparator的原因是因为它是TreeSet API的一部分。引用{{3}}:

  

TreeSet是)基于NavigableSet的{​​{1}}实施。元素按照它们的自然顺序排序,或者在创建时创建时提供TreeMap,具体取决于使用的构造函数。

改变这些事情会破坏合同。

答案 1 :(得分:0)

TreeSet保持其元素排序。如果您提供比较器,它会使用该自定义比较器(在您的情况下为MyNameComp()或MySalaryComp())来比较和排序它们。你不需要调用任何东西,TreeSet将在内部处理它。