Set:唯一
  --HashSet:无序,唯一
    ----LinkedHashSet:采用的存储为哈希表+链表的结构(java.util.LinkedHashSet实现了Set接口,继承HashSet)
  --TreeSet:唯一,有序(大小顺序)

Set接口继承Collection接口,没有额外添加方法
  特点:唯一(不重复),无序(位置顺序),无法通过下标索引获取元素
 其下有三个常用的实现类
   HashSet***
    常用的构造函数
      HashSet():构造一个新的空 set,其底层 HashMap 实例的默认初始容量是 16,加载因子是 0.75。
      HashSet(int initialCapacity):构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)
    常用的函数:
      add(E e):如果此 set 中尚未包含指定元素,则添加指定元素。
      size():获取容器中元素的个数
      iterator():返回对此 set 中元素进行迭代的迭代器。
      isEmpty():如果此 set 不包含任何元素,则返回 true。
      contains(Object o) :如果此 set 包含指定元素,则返回 true。
      remove(Object o):如果指定元素存在于此 set 中,则将其移除。
    遍历方式:
      1.使用for-each遍历
      2.使用迭代器进行遍历
  TreeSet*

  LinkedHashSet

 

public class TestHashSet {
    public static void main(String[] args) {
        Set<String> set = new HashSet<String>();
        System.out.println("容器是否为空:"+set.isEmpty());
        set.add("java");
        set.add("oracle");
        set.add("html");
        set.add("java");
        System.out.println("元素的个数:"+set.size());
        System.out.println("容器是否为空:"+set.isEmpty());
        System.out.println("是否包含java:"+set.contains("java"));
        //1.使用for-each进行遍历
        for (String string : set) {
            System.out.println(string);
        }
        System.out.println("------");
        //2.使用迭代器进行遍历
        Iterator<String> iter = set.iterator();
        while(iter.hasNext()){
            String str = iter.next();
            System.out.println(str);
        }
    }
}

 

HashSet存储结构采用hashtable(哈希表+链表结构进行存储)
  优点:
    查询(哈希算法),添加,删除速(链表)度快
    hashcode(哈希码):同哈希码计算对象的存储位置 y=k(x)
    y:代表存储位置 x:哈希码
  缺点:无序(位置顺序),无法通过下标访问--->get(i)
    添加情况:添加时会计算存储位置--->获取哈希码--->通过调用hashcode()获取哈希码
    情况1:一次添加成功
    情况2:多次添加,存在重复,去掉重复项--->通过 equals()内容是否一致
    情况3:在相同位置,多次添加成功
hashcode()与equals()的关系
  1。hashcode相同,equals()是不一定相同
  2.equals()比较两个对象内容相同(值为true),hashcode值是一定相同

注意:
  hashSet中去掉重复项会调用hashCode()和equals()
  需要重写Object类中hashCode()和equals()
  1.先调用hashCode()获取对象的hash码,如果hash码不相同,对象肯定不同,不再调用equals方法进行比较
    提高了效率:
      传统做法:如果要比较1000的对象,需要调用1000次的equals()方法
      使用hash码:先比较hash是否相同,如果hash码相同才调用equals进行比较
  2.通过hash码计算存储位置: y=k(x)

hashCode如何计算:
  1.Integer类型:用自身数值做hashcode
  2.Student

package cn.zzsxt.set1;

public class Student {
    private String name;
    private int age;
    public Student(){
        
    }
    public Student(String name,int age){
        this.name=name;
        this.age=age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    @Override
    public String toString() {
        return "姓名:"+name+",年龄:"+age;
    }
    @Override
    public int hashCode() {
        System.out.println("hashCode方法被调用了...");
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        System.out.println("equals方法被调用了....");
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

    
}
public class TestHashSet2 {
    public static void main(String[] args) {
        Set<Student> set = new HashSet<Student>();
        Student stu1 = new Student("zhangsan",20);
        Student stu2 = new Student("zhangsan2",22);
        Student stu3 = new Student("zhangsan3",23);
        Student stu4 = new Student("zhangsan2",22);//??
        Student stu5 = new Student("zhangsan2",22);//??
//        set.add("java"); //一旦使用泛型,该容器只能保存指定的数据类型
        set.add(stu1);
        set.add(stu2);
        set.add(stu3);
        set.add(stu4);
        set.add(stu5);
        System.out.println(set.size());
        for (Student student : set) {
            System.out.println(student);//System.out.println(student.toString());
        }
        
    }
}

 

Set:唯一
    --HashSet:无序,唯一
      ----LinkedHashSet:采用的存储为哈希表+链表的结构
    --TreeSet:唯一,有序(大小顺序)

java.util.LinkedHashSet实现了Set接口,继承HashSet
  特点:唯一,有序(位置顺序)
  常用的构造函数
    LinkedHashSet():构造一个带默认初始容量 (16) 和加载因子 (0.75) 的新空链接哈希 set。
    LinkedHashSet(int initialCapacity):构造一个带指定初始容量和默认加载因子 (0.75) 的新空链接哈希 set。
  常用方法:
    add(E e):添加
    remove(E e):移除指定元素
    size():查看容器元素的个数
    contains(E e):是否包含指定元素
    iterator():返回一个迭代器

public class TestLinkedHashSet {
    public static void main(String[] args) {
        LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();
        linkedHashSet.add("java");
        linkedHashSet.add("oracle");
        linkedHashSet.add("html");
        linkedHashSet.add("html");
        linkedHashSet.remove("java");//
        System.out.println("元素个数:"+linkedHashSet.size());
        System.out.println("是否包含java:"+linkedHashSet.contains("java"));
        //采用遍历:for-each
        for (String string : linkedHashSet) {
            System.out.println(string);
        }
        System.out.println("--------------------------");
        //采用迭代器:Iterator
        for(Iterator<String> iter = linkedHashSet.iterator();iter.hasNext();){
            String str = iter.next();
            System.out.println(str);
        }
    
    }
}

 

TreeSet:采用二叉树进行存储,实现类Set接口
  特点:唯一,有序(自然顺序)
  优点:
    查找效率比List要高,但没有HashSet高
  构造函数:
    TreeSet():构造一个新的空 set,该 set 根据其元素的自然顺序进行排序。

public class TestTreeSet {
    public static void main(String[] args) {
        TreeSet<String> treeSet = new TreeSet<String>();
        treeSet.add("java");
        treeSet.add("oracle");
        treeSet.add("html");
        treeSet.add("aa");
        treeSet.add("ab");
//        treeSet.add("html");
        System.out.println("元素个数:"+treeSet.size());
        //使用for-each遍历
        for (String string : treeSet) {
            System.out.println(string);
        }
    }

}

 

TreeSet存储对象的方法

package cn.zzsxt.set2;

public class Student implements Comparable<Student>{
    
    private String name;
    private int age;
    private int score;
    
    public Student() {
    }

    public Student(String name, int age, int score) {
        this.name = name;
        this.age = age;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + score;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (score != other.score)
            return false;
        return true;
    }

    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
    }
    /**
     * 重写Compareable接口中的方法
     * 完成比较业务逻辑
     * 按照分数为第一顺序倒序
     * 年龄为第二顺序进行倒序存放
     * 
     */
    @Override
    public int compareTo(Student o) {
        if(this.score>o.score){
            return -1;
        }else if(this.score==o.score){
            if(this.age>o.age){
                return -1;
            }else if(this.age==o.age){
                return 0;
            }else{
                return 1;
            }
        }else {
            return 1;
        }
    }
    
    
}

 

出现异常:java.lang.ClassCastException
  导致原因:TreeSet采用的二叉树进行存放(对要保存的元素要求有大小顺序,如果要比较对象大小必须实现Compareable接口,重写compareTo方法)
 需求:
  按照分数为第一顺序,年龄为第二顺序进行存放

public class TestTreeSet {
    public static void main(String[] args) {
        TreeSet<Student> treeSet = new TreeSet<Student>();
        Student stu1 = new Student("zhangsan",20,80);
        Student stu2 = new Student("lisi",21,82);
        Student stu3 = new Student("wangwu",22,80);
        Student stu4 = new Student("wangwu",22,80);
        treeSet.add(stu1);
        treeSet.add(stu2);
        treeSet.add(stu3);
        treeSet.add(stu4);
        for (Student student : treeSet) {
            System.out.println(student);//调用student中的toString()方法
        }
    }
}

 

 

 构造函数:
  TreeSet()构造一个新的空 set,该 set 根据其元素的自然顺序进行排序(本质上调用对象中重写Comparable接口中compareTo方法)。
    构造一个新的空 TreeSet,它根据指定比较器进行排序
  TreeSet(Comparator<? super E> comparator)
    构造一个新的空 TreeSet,它根据指定比较器进行排序。
  java.util.Comparator:比较器接口,可能更加灵活的完成对象的比较

package cn.zzsxt.set2;

import java.util.Comparator;

public class LengthCom implements Comparator<Student> {
    /**
     * 比较用来排序的两个参数。
     * 根据第一个参数小于、等于或大于第二个参数分别返回负整数、零或正整数
     */
    @Override
    public int compare(Student o1, Student o2) {
        int len1 = o1.getName().length();
        int len2 = o2.getName().length();
        if(len1>len2){
            return 1;
        }else if(len1==len2){
            return 0;
        }else{
            return -1;
        }
    }

}
public class TestTreeSet2 {
    public static void main(String[] args) {
        //创建一个比较器
        LengthCom lencom = new LengthCom();
        //它根据指定比较器进行排序
        TreeSet<Student> treeSet = new TreeSet<Student>(lencom);
        Student stu1 = new Student("zhangsan",20,80);
        Student stu2 = new Student("lisi",21,82);
        Student stu3 = new Student("wangwu",22,80);
        treeSet.add(stu1);
        treeSet.add(stu2);
        treeSet.add(stu3);
        for (Student student : treeSet) {
            System.out.println(student);//调用student中的toString()方法
        }
    }
}

 


需求:
按照姓名的长度进行排序