11.集合之set

set

  • set接口用于存储无序并且元素不可重复的集合,如下图:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3e4grplS-1599911871739)(D:\downfile\QQ\tu2.png)]

  • set接口常用的实现子类有HashSet、LinkedHashSet、TreeSet类等。

1 HashSet

  • HashSet是set集合中最常用的实现类,HashSet是按照哈希算法来存储的,因此具有很好的存取和查找性能。

  • HashSet特点:

    1. 无序,不能保证元素的顺序
    2. HashSet不是线程同步的,如果多线程操作HashSet集合,则应通过代码来实现线程同步。
    3. 集合元素可以为null
  • 案例1:

    public class Test {
    	public static void main(String[] args) {
    		HashSet dest = new HashSet();
    		dest.add(1);
    		dest.add(71);
    		dest.add(23);
    		dest.add(67);
    		dest.add(98);
    		
    		
    		for (Object object : dest) {
    			System.out.print(" "+object);
    		}
    		System.out.println("\n===========================");
    		
    		//因为此循环是无序的,我们不能通过for循环遍历该集合
    		//我们可以通过迭代器让无序的集合"排队"
    		
    		Iterator it = dest.iterator();
    		while (it.hasNext()) {
    			Object obj = it.next();
    			System.out.print(" "+obj);
    		}
    		
    	}
    }
    
  • 结果

     1 98 67 71 23
    ===========================
     1 98 67 71 23
    
  • 案例2:

    import java.util.HashSet;
    
    public class Test02 {
    	public static void main(String[] args) {
    		Student stu1 = new Student("马云",45,'男');
    		Student stu2 = new Student("马化腾",46,'男');
    		Student stu3 = new Student("董明珠",47,'女');
    		Student stu4 = new Student("章泽天",28,'女');
    		
    		HashSet<Student> dest = new HashSet<Student>();
    		dest.add(stu1);
    		dest.add(stu2);
    		dest.add(stu3);
    		dest.add(stu4);
    		
    		for (Student student : dest) {
    			student.showStudent();
    		}	
    	}
    }
    
  • 结果

    你好我是董明珠年龄:47性别:女
    你好我是马云年龄:45性别:男
    你好我是马化腾年龄:46性别:男
    你好我是章泽天年龄:28性别:

2 LinkedHashSet

  • LinkedHashSet是介于HashSet和TreeSet之间,内部是一个双向链表结构,所以它插入是有序的。linkedHashSet是HashSet的一个子类,具有HashSet的特性,也是根据元素的HashCode值来决定元素的存储位置。但它使用链表维护元素的次序,元素的顺序与添加顺序一致,由于LinkedHashSet需要维护元素的插入顺序,因此性能上略低于Hashset,但在迭代访问Set里面的全部元素时候由有很好的性能。

  • 案例

    import java.util.Iterator;
    import java.util.LinkedHashSet;
    
    public class Test {
    	public static void main(String[] args) {
    		//以链表式和Hash算法相结合,插入有序的set集合
    		LinkedHashSet lset = new LinkedHashSet();
    		lset.add(1);
    		lset.add(4);
    		lset.add(7);
    		lset.add(2);
    		lset.add(5);
    		lset.add(8);
    		
    		for (Object object : lset) {
    			System.out.print(" " + object);
    		}
    		
    		System.out.println("\n======================");
    		Iterator it = lset.iterator();
    		while (it.hasNext()) {
    			Object obj = it.next();
    			System.out.print(" "+obj);
    		}
    	
    	}
    }
    
  • 结果

     1 4 7 2 5 8
    ======================
     1 4 7 2 5 8
    

3 TreeSet

  • TreeSet是sortedSet接口的实现类,TreeSet可以保证元素处于排序状态,它采用的是红黑树算法的数据结构来存储集合元素.TreeSet支持两种排序方法:自然排序和定制排序,默认采用自然排序。

  • 案例:

    import java.util.Iterator;
    import java.util.TreeSet;
    
    public class Test {
    	public static void main(String[] args) {
    		TreeSet tree = new TreeSet();
    		tree.add(1);
    		tree.add(41);
    		tree.add(54);
    		tree.add(32);
    		tree.add(4);
    		tree.add(52);
    
    		Iterator<Integer> it = tree.iterator();
    		while (it.hasNext()) {
    			Integer val = it.next();
    			System.out.print(" "+val);
    		}
    	}
    }
    
  • 结果:会自然排序插入到集合中

     1 4 32 41 52 54
    
  • 自然排序

    TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素的大小,然后将元素按照升序排序,这就是自然排序。
    
  • 定制排序

    1.如果Treeset集合插入的是对象,那么对象是无法去比较排序的,所以我们需要通过定制排序来定制对象之间排序的规则。
    2.需要在创建TreeSet集合对象时,提供一个comparator对象与该TreeSet集合关联,由comparator对象负责集合元素的排序规则。
    
  • 实现步骤:

    1. 在集合的元素的类里面实现comparator接口

      public class Student implements Comparable<Student>{
      	private String name;
      	private int age;
      	
      	public void showStudent(){
      		System.out.println("你好我是"+name+",年龄是:"+age);
      	}
      	
      	public Student() {
      		super();
      	}
      	public Student(String name, int age) {
      		super();
      		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;
      	}
      
      	/** 
      	 * 	重写compareTo方法,自定义比较规则
      	 * 	如果两个对象的值相等返回0
      	 * 	obj1对象大于obj2对象返回正数
      	 * 	obj1对象小于obj2对象返回负数
      	 * 	返回的结果不需要关心,你只需要返回正数、负数、0这三种结果即可,底层其它方法根据你的结果去比较排序
      	 */
      	@Override
      	public int compareTo(Student stu) {
      		int num = this.age-stu.age;
      		return num;
      	}
      }
      
    2. 重写compareto(Object obj)方法自定义排序规则

      import java.util.TreeSet;
      
      public class Test1 {
      	public static void main(String[] args) {
      		Student stu1 = new Student("马云",45);
      		Student stu2 = new Student("马化腾",40);
      		Student stu3 = new Student("董明珠",47);
      		Student stu4 = new Student("章泽天",28);
      		
      		TreeSet<Student> tree = new TreeSet<Student>();
      		tree.add(stu1);
      		tree.add(stu2);
      		tree.add(stu3);
      		tree.add(stu4);
      		
      		for (Student student : tree) {
      			student.showStudent();
      		}
      	}
      }
      
    3. 结果

      你好我是章泽天,年龄是:28
      你好我是马化腾,年龄是:40
      你好我是马云,年龄是:45
      你好我是董明珠,年龄是:47
      

4 EnumSet

  • EnumSet是一个专门用来存放枚举类型的集合,不允许添加null值。EnumSet集合元素也是有序的,它是以枚举值在Enum类内的定义顺序来决定集合元素的顺序。

5 各set集合实现类的性能分析

  • HashSet的性能比TreeSet性能好,因为TreeSet需要额外通过红黑树算法来维护元素次序,如果需要保持一个排序的set时候用TreeSet,否则应该使用HashSet
  • LinkedHashSet是HashSet的子类,由于需要维护链表的顺序,所以插入和删除操作比HashSet要慢,但遍历比Hashset要快
  • EnumSet是所有实现类中性能最慢的,但它只能用于保存同一个枚举类的枚举值作为元素的集合。
  • 以上几个Set实现类都是非线程安全的,如果需要多线程访问,必须手动包装集合的同步性。
  • 必须学会:ArrayList、LInkedList、hashSet
     public class Test1 {
     	public static void main(String[] args) {
     		Student stu1 = new Student("马云",45);
     		Student stu2 = new Student("马化腾",46);
     		Student stu3 = new Student("董明珠",47);
     		Student stu4 = new Student("章泽天",28);
     		
     		Map<String,Student> map = new Hashtable<String,Student>();
     		map.put(stu1.getName(), stu1);
     		map.put(stu2.getName(), stu2);
     		map.put(stu3.getName(), stu3);
     		map.put(stu4.getName(), stu4);
     		//map转换list
     		List<Student> list = CollectionUtils.getMapTranToList(map);
     		
     		for (Student student : list) {
     			student.showStudent();
     		}
     	}
     }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值