• JAVA基础-集合Set


    首先总结一下集合的体系:

    集合 的体系:
    ------------| Collection 单例集合的根接口
    ----------------| List 如果是实现了List接口的集合类,具备的特点: 有序,可重复。
    -------------------| ArrayList 底层是维护了一个Object数组实现的。 特点: 查询速度快,增删慢。
    -------------------| LinkedList 底层是使用了链表数据结构实现的, 特点: 查询速度慢,增删快。
    -------------------| Vector(了解即可) 底层也是维护了一个Object的数组实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低。

    ----------------| Set 如果是实现了Set接口的集合类,具备的特点: 无序,不可重复。
    -------------------| HashSet 底层是使用了哈希表来支持的,特点: 存取速度快.
    -------------------| TreeSet 如果元素具备自然顺序 的特性,那么就按照元素自然顺序的特性进行排序存储。

    Set

    Set 集合,元素是无序的,而且不能重复的。

    重点掌握 HashSet 实现类的使用。

    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    public class SetDemo {
    
    	public static void main(String[] args) {
    		Set s1=new HashSet<>();
    		s1.add("ddd");
    		s1.clear();
    		s1.remove("ddd");
    		Iterator i1 = s1.iterator();
    	}
    }
    

    HashSet

    HashSet的特点:

    1. 添加的元素是无序的。

    2. HashSet 不是同步的,如果多个线程同时访问一个 HashSet,比如在修改时,一定要手动通过代码来保证同步,也就是保证安全。

    3. 集合元素值可以是 null

    一些基本的用法:

    import java.util.HashSet;
    import java.util.Iterator;
    
    public class HashSetDemo {
    
    	public static void main(String[] args) {
    		//hashset  存储数据唯一(不可重复)   无序
    		HashSet<String> hs=new HashSet<String>();
    		hs.add("张三");
    		hs.add("张三");
    		
    		System.out.println(hs);
    		System.out.println(hs.size());
    		
    		//遍历  foreach   迭代器
    		for (String string : hs) {
    			System.out.println("foreach:"+string);
    		}
    		//
    		Iterator<String> i1=hs.iterator();
    		while(i1.hasNext()) {
    			System.out.println("迭代器:"+i1.next());
    		}
    		
    	}
    }
    
    

    另外,我们从下面的代码可以看出一些hashset的特性,在这里,我们想要让hashset存储数据时不重复存储(因为每new一个对象,其索引不一样,且hash值也不同,即使我们new出的两个对象包含同样的信息,hashset依然会判定为两个不同的对象),我们做两个操作:

    1. 重写public boolean equals(Object obj)方法

    2. 重写public int hashCode() 方法

    这么做的原因是:
    往 HashSet 集合中添加一个元素的时候,默认调用 hashCode() 方法得到该对象的 hashCode 值,用于决定该对象在 HashSet 中存放的位置。
    如果两个元素,通过 equals() 方法比较返回 true,但 hashCode() 返回的值不一样,说明两个元素是不 一样的,则允许添加。
    所以,HashSet 集合判断两个元素是否相等,就是通过 equals() 方法还有 hashCode 值也一起比较。将来,如果有需要自定义一些判断方法,则可以模仿这里的操作方式。

    import java.util.HashSet;
    
    //人类
    public class Person{
    
    	String name;
    	int age;
    	String sex;
    
    	public Person(String name, int age, String sex) {
    		super();
    		this.name = name;
    		this.age = age;
    		this.sex = sex;
    	}
        
    	@Override
    	public int hashCode() {
    	// TODO Auto-generated method stub
    		return age;
    	}
        
    	//案例 主要对象中姓名 年龄  和性别是相同的 就判断同一个对象使用set保存后体现唯一性
    	//根据性别 姓名 年龄
    	@Override
    	public boolean equals(Object obj) {
    		Person p1=(Person) obj;
    		if(this.sex.equals(p1.sex)) {
    			if(this.name.equals(p1.name)) {
    				if(this.age==p1.age) {
    					return true;
    				}
    			}
    		}
    
    		return  false;
    	}
    	//alt +Shift+s 弹出窗口 
    	public static void main(String[] args) {
    		//需求 使用hashset集合 存储4个person对象 并打印输出出来 哈希吗值也有关系
    		HashSet<Person> phSet=new HashSet<Person>();
    		Person zhangsan=new Person("张三", 18, "男");
    		Person zhangsan2=new Person("张三", 18, "男");
    
    		Person lisi=new Person("李四", 18, "男");
    		Person wangwu=new Person("王五", 18, "男");
    		Person qianliu=new Person("钱六", 18, "男");
    		phSet.add(zhangsan);
    		phSet.add(lisi);
    		phSet.add(wangwu);
    		phSet.add(qianliu);
    		phSet.add(zhangsan2);
    		System.out.println(phSet);
    	}
    
    	@Override
    	public String toString() {
    		return "Person [name=" + name + ", age=" + age + ", sex=" + sex + "]";
    	}
    }
    

    LinkedHashSet

    LinkedHashSet 从名字上看,跟“链式”有关,它也是根据元素的 hashCode 值来决定元素的存储位置, 但还多使用链表来维护元素的顺序。

    访问它的时候,会根据元素的添加顺序来访问集合中的元素,有个好处,访问时的性能会很好。

    因为是链式的结构,在插入数据的时候,性能略差于 HashSet,插入元素时不建议使用。

    import java.util.LinkedHashSet;
    
    public class LinkedHashSetDemo {
    
    	public static void main(String[] args) {
    		//无序  唯一的
    		//链表结构与哈希吗值都有关系
    		//与hashset相比  访问快  插入慢
    		//方法同 hashset一样用
    		LinkedHashSet<String> lhs =new LinkedHashSet<String>();
    		lhs.add("张三");
    		lhs.add("张三");
    		lhs.add("张三");
    		lhs.add("张三");
    		lhs.add("张三");
    		System.out.println(lhs);
    //		lhs.remove("zhangsan");
    		
    	}
    }
    
    
    public class TreeSetTest { 
        public static void main(String[] args) { 
            TreeSet nums = new TreeSet(); 
            // 向 TreeSet 中添加对象 
            nums.add(5); 
            nums.add(2); 
            nums.add(10); 
            nums.add(-9); 
            // 输出集合元素,看到集合元素已经处于排序状态 
            // 并没有按添加的先后顺序进行排列
            System.out.println(nums);
            // 输出集合里的第一个元素 
            System.out.println(nums.first()); 
            // 输出-9 
            // 输出集合里的最后一个元素 
            System.out.println(nums.last()); 
            // 输出10 
            // 返回小于4的子集,不包含4 (左闭右开)
            System.out.println(nums.headSet(4)); 
            // 输出[-9, 2] 
            // 返回大于5的子集,如果Set中包含5,子集中还包含5 (左闭右开)
            System.out.println(nums.tailSet(5)); 
            // 输出 [5, 10] 
            // 返回大于等于-3,小于4的子集。 
            // -3 < x < 4 
            System.out.println(nums.subSet(-3, 4)); 
            // 输出[2] 
        } 
    }
    

    TreeSet

    不同于hashset是根据哈希值来存储元素,TrerSet借助了红黑树来存储对象,虽然不可索引,但是内部依然是按顺序排列的。

    TreeSet 可保证元素处于排序的状态,所以 TreeSet 采用的是红黑树的数据结构来存储集合元素的。

    排序规则有:自然排序(默认)和定制排序。

    import java.util.TreeSet;
    
    public class TreeSetDemo {
    
    	public static void main(String[] args) {
    		//存储红黑二叉树数据结构 会对数进行排序存储
    		TreeSet ts=new TreeSet();
    		ts.add(222);
    		ts.add(13);
    		ts.add(2);
    		ts.add(33);
    		ts.add(4);
    		ts.add(1);
    		System.out.println(ts);
    		System.out.println("最高的"+ts.last());
    		System.out.println("最小的"+ts.first());
    		System.out.println("检索最小元素返回并删除"+ts.pollFirst());
    		System.out.println("检索最大元素返回并删除"+ts.pollLast());
    		System.out.println(ts);
    		//遍历 foreach  迭代器
    		
    	}
    }
    
    

    TreeSet 会调用 compareTo(Object obj) 方法来比较元素之间的大小关系,按升序进行排列。

    此方法属于 Comparable 接口,将返回一个整数值,实现该接口的类就可以用返回值来比较大小。

    Comparable 接口,主要提供了比较大小的标准,有些将来会碰到的常用类:BigDecimal、 BigInteger、Character、Boolean、String 、Date、Time 等。 当我们在Treeset中插入一个我们自己写的对象的时候会报错,其原因就是TreeSet利用compareTo(Object obj) 方法来比较元素之间的大小,所以我们需要将我们要比较的对象实现Comparable 接口。

    当 TreeSet 添加元素时,会调用 compareTo() 方法先去比较大小和根据红黑树去查找位置,如果通过

    compareTo() 方法比较相等,就不能再添加了,所以下面的代码Set中只有一个元素。

    下面是我们要放入TreeSet的对象,我们实现了Comparable<T>方法:

    import java.util.Comparator;
    
    public class Pet implements Comparable<Pet>{
    
    	String name;
    	String color;
    	int age;
    	public Pet(String name, String color, int age) {
    		super();
    		this.name = name;
    		this.color = color;
    		this.age = age;
    	}
    	@Override
    	public String toString() {
    		return "Pet [name=" + name + ", color=" + color + ", age=" + age + "]";
    	}
    	//treeset比较方法  原理红黑二叉树数据结构
    	@Override
    	public int compareTo(Pet o) {
    		return 0;
    	}
    }
    
    import java.util.TreeSet;
    
    public class TreeSetDemo2 {
    
    	public static void main(String[] args) {
    		TreeSet<Pet> ts=new TreeSet<Pet>();
    		ts.add(new Pet("妮妮", "白色", 18));
    		ts.add(new Pet("妮妮", "白色", 18));
    
    		System.out.println(ts);
    	}
    }
    

    同时呢,如果想要实现我们自定义的排序方式,可以利用内部类的方法来实现:

    import java.util.Comparator;
    import java.util.TreeSet;
    
    public class Pet2 {
    
    	int age;
    	
    	
    	public Pet2(int age) {
    		super();
    		this.age = age;
    	}
    	
    	@Override
    	public String toString() {
    		return "Pet2 [age=" + age + "]";
    	}
    
    	//
    	
    	public static void main(String[] args) {
    //		TreeSet<Pet2> treeSet=new TreeSet<Pet2>();
    //		treeSet.add(new Pet2(18));
    //		treeSet.add(new Pet2(17));
    //		treeSet.add(new Pet2(2));
    //		System.out.println(treeSet);
    		//方式2  定制排序
    		TreeSet<Pet2> t2=new TreeSet<Pet2>(new Comparator<Pet2>() {
    
    			@Override
    			public int compare(Pet2 o1, Pet2 o2) {
    				// TODO Auto-generated method stub
    				//比较
    				return o1.age>o2.age?-1:o1.age<o2.age?1:0;
    			}
    		});
    		
    		//降序
    		t2.add(new Pet2(18));
    		t2.add(new Pet2(1));
    		t2.add(new Pet2(23));
    		System.out.println(t2);
    	}
    
    }
    
  • 相关阅读:
    SpringBoot配置Druid数据源
    springboot自定义异常处理
    SpringBoot配置详解
    设计模式 | 模板方法模式(template method)
    设计模式 | 原型模式(prototype)
    设计模式 | 工厂方法模式(factory method)
    设计模式 | 代理模式(proxy)
    设计模式 | 装饰模式(decorator)
    设计模式 | 策略模式(strategy)
    设计模式 | 简单工厂模式(static factory method)
  • 原文地址:https://www.cnblogs.com/JeasonIsCoding/p/13232527.html
Copyright © 2020-2023  润新知