java学习【知识点及代码11】

集合3_Set
1.Set
1.1常用方法:直接查看api,里面的方法我们基本都是学过

2.HashSet(查询api看说明进行讲解)
2.1 元素顺序:元素唯一,但是无序(它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变)
案例:创建一个HashSet集合,添加元素(String元素),测试唯一性,无序性

2.2如何保证元素的唯一性的呢(分析源码)?
* 通过简单的分析,我们知道HashSet集合保证元素的唯一性和add()方法相关。
* 如果我们想深入的了解,就必须看add()方法的源码,看它的底层依赖什么内容?
* if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {…}
*
* 左边:e.hash == hash
* 比较对象的哈希值。
*
* 右边:((k = e.key) == key || key.equals(k))
* 左边:(k = e.key) == key
* 比较对象的地址值。
*
* 右边:key.equals(k)
* 比较的是对象的内容是否相同。默认情况下比较的是地址值

结论:
底层数据结构是哈希表。
哈希表依赖两个方法:hashCode()和equals()


执行流程:
    首先判断哈希值是否相同,如果不同,就直接添加到集合。
    如果相同,继续执行equals(),看其返回值,
    如果是false,就直接添加到集合。
    如果是true,说明元素重复不添加。


使用:
    如果你看到哈希结构的集合,就要考虑可能需要重写这两个方法。
    如果真要重写,自动生成即可。

画图讲解哈希表结构:是一个元素为链表的数组结构

这里写图片描述
知识点demo演练:
1.存储String类型的元素,说明元素无序且唯一

package com.edu_01;

import java.util.HashSet;
import java.util.Set;

public class HashSetDemo {
    public static void main(String[] args) {
        //创建一个HashSet集合
        HashSet<String> set = new HashSet<String>(); 

        //给集合中添加元素
        set.add("hello");
        set.add("java");
        set.add("world");
        set.add("c++");
        set.add("php");
        set.add("hello");

        //遍历集合
        /**
         * HashSet集合特点:
         * 1.元素无序
         * 2.元素唯一
         */
        for (String string : set) {
            System.out.println(string);
        }       
    }
}

2.分析add()方法,保证唯一性的原理(底层依赖于hashCode()和equals()方法,保证了元素的唯一性)
3.存储自定义对象,如何保证元素的唯一性?(存储相同元素,发现无法保证元素的唯一性)

package com.edu_02;

import java.util.HashSet;

public class HashSetDemo {
    //3.存储自定义对象,如何保证元素的唯一性?
    /**
     * hashSet集合保证元素的唯一性依赖两个方法:hashCode()--为了让元素的哈希吗值相同,
     *                               equals()-- 比较元素的成员变量值是否相同
     *                               
     * 在hashset集合中为了保证元素的唯一性,就必须重写存入hashset集合中元素所对应的类中hashCode(),equals()
     * 
     */
    public static void main(String[] args) {
        //创建集合
        HashSet<Student> hs = new HashSet<Student>();

        //创建学生对象
        Student s1 = new Student("小敏",15);
        Student s2 = new Student("小华", 12);
        Student s3 = new Student("小张",16);
        Student s4 = new Student("小明", 13);
        Student s5 = new Student("小李", 16);

        //给集合中添加元素
        hs.add(s1);
        hs.add(s2);
        hs.add(s3);
        hs.add(s4);
        hs.add(s5);

        //遍历集合
        for (Student student : hs) {
            System.out.println(student);
        }       
    }
}
package com.edu_02;

public class Student {
    private String name;
    private int age;
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    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 "Student [name=" + name + ", age=" + age + "]";
    }

    //重写hashCode(),equals()方法
    @Override
    public int 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) {
        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;
    }
}

3.TreeSet(查看api,得出结论)
3.1 元素顺序:使用元素的自然顺序对元素进行排序,或者根据创建set时提供的 Comparator进行排序(比较器排序),
具体取决于使用的构造方法。
3.2 底层算法:二叉树(画图进行讲解)
这里写图片描述
3.3 元素要求, 加入自定义JavaBean

案例演练:
1.创建集合存储Integer类型的元素(20,18,23,22,17,24,19,18,24),分析如何保证元素唯一性,以及排序的规则。二叉树
(首先讲解二叉树数据结构是怎么存入元素的,根据compareTo()方法的返回值来确定要存入元素的安放位置)

package com.edu_03;

import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        //创建一个TreeSet集合
        /**
         * TreeSet集合特点:
         * 1.元素唯一
         * 2.元素有序
         */
        TreeSet<Integer> ts = new TreeSet<Integer>();

        //给集合中存储元素
        //(20,18,23,22,17,24,19,18,24)
        ts.add(20);
        ts.add(18);
        ts.add(23);
        ts.add(22);
        ts.add(17);
        ts.add(24);
        ts.add(19);
        ts.add(18);
        ts.add(24);

        //遍历集合
        for (Integer integer : ts) {
            System.out.println(integer);
        }       
    }
}

2.存储字符串并遍历(字母a-z排序)

package com.edu_03;

import java.util.TreeSet;

public class TreeSetDemo2 {
    public static void main(String[] args) {
        //创建一个TreeSet集合
        //当存入字符串的时候,按照字典顺序进行排序
        TreeSet<String> ts = new TreeSet<String>();

        //存入字符串
        ts.add("linzhiling");
        ts.add("amu");
        ts.add("bigbang");
        ts.add("guodegang");

        //遍历集合
        for (String string : ts) {
            System.out.println(string);
        }       
    }
}

3.存入学生对象(姓名,年龄),1.按年龄排序,2.姓名排序(自然排序实现Comparable接口,并重写comparaTo()方法)

package com.edu_04;

import java.util.TreeSet;
/**
 * java.lang.ClassCastException:类型转换异常
 * 
 * TreeSet集合有两种排序方式:至于哪两种排序方式,取决于他的构造器
 *  
 * 自然排序:无参构造public TreeSet()
 * 
 * 比较器排序(Comparator):
 *
 *
 */
public class TreeSetDemo {
    public static void main(String[] args) {
        //创建TreeSet集合,存储自定义对象
        TreeSet<Student> ts = new TreeSet<Student>();

        //给集合中添加Student对象
        Student s = new Student("guodegang", 50);
        Student s6 = new Student("liuyifei", 50);
        Student s2 = new Student("zhangxueyou", 55);
        Student s3 = new Student("amu", 45);
        Student s4 = new Student("tf-boys", 18);
        Student s5 = new Student("wangfeng", 49);

        ts.add(s);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);

        //遍历集合
        for (Student student : ts) {
            System.out.println(student);
        }
    }
}
package com.edu_04;

public class Student implements Comparable<Student>{
    private String name;
    private int age;
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    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 "Student [name=" + name + ", age=" + age + "]";
    }

    //实现Comparable接口的同时必须实现这个比较法
    @Override
    public int compareTo(Student s) {
        //就是写的是元素的比较规则,由你自己去动手写出
        //按照学生的年龄进行排序
        /**
         * 两个对象进行比较:
         * s
         * this
         */
        int num = this.age - s.age;
        //判断年龄是否相同,如果相同比较姓名
        /**
         * 写这个比较规则的时候注意两点:
         * 1.他有主要条件,先按照主要条件进行排序
         * 2.如果主要条件相同,就需要你自己分析出来他的次要条件,再去按照次要条件进行比较
         */

        int num2 = num==0?this.name.compareTo(s.name):num;
        return num2;
    }   
}

4.创建set集合的时候,传入Comparator(比较器排序)进行排序,进行排序(比较器排序)

package com.edu_05;

public class Student{
    private String name;
    private int age;
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    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 "Student [name=" + name + ", age=" + age + "]";
    }   
}
package com.edu_05;

import java.util.Comparator;

public class ComparatorImpl implements Comparator<Student>{

    @Override
    public int compare(Student s1, Student s2) {
        /**
         * s1--this
         * s2 -- s
         * 按照年龄进行排序,年龄相同按照姓名排序
         * 
         */
        int num = s1.getAge() - s2.getAge();
        int num2 = num==0?s1.getName().compareTo(s2.getName()):num;
        return num2;
    }
}
package com.edu_05;

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

public class TreeSetDemo {
    public static void main(String[] args) {
        //创建集合,参数是一个接口,实际需要的是接口的实现类对象
        //TreeSet<Student> ts = new TreeSet<Student>(new ComparatorImpl());

        //使用匿名内部类来进行改进
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getAge() - s2.getAge();
                int num2 = num==0?s1.getName().compareTo(s2.getName()):num;
                return num2;
            }
        });

        //创建对象存入集合
        Student s = new Student("guodegang", 50);
        Student s6 = new Student("liuyifei", 50);
        Student s2 = new Student("zhangxueyou", 55);
        Student s3 = new Student("amu", 45);
        Student s4 = new Student("tf-boys", 18);
        Student s5 = new Student("wangfeng", 49);

        ts.add(s);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);

        //遍历集合
        for (Student student : ts) {
            System.out.println(student);
        }       
    }
}

比较器排序eg:

package com.edu_07;

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

public class TreeSetDemo {
    public static void main(String[] args) {
        //创建一个TreeSet集合,使用比较器排序
        TreeSet<Car> ts = new TreeSet<>(new Comparator<Car>() {
            @Override
            public int compare(Car c1, Car c2) {
                int num = c1.getPrice() - c2.getPrice();
                int num2 = num==0?c1.getBrand().compareTo(c2.getBrand()):num;
                return num2;
            }
        });

        //创建汽车对象
        Car c1 = new Car("lanbojini", 1000);
        Car c2 = new Car("tesila", 1000);
        Car c3 = new Car("mashaladi", 2000);

        //存入集合
        ts.add(c1);
        ts.add(c2);
        ts.add(c3);

        //遍历集合
        Iterator<Car> it = ts.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }       
    }
}
package com.edu_07;

public class Car{
    private String brand;
    private int price;
    public Car(String brand, int price) {
        super();
        this.brand = brand;
        this.price = price;
    }
    public Car() {
        super();
        // TODO Auto-generated constructor stub
    }
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
    @Override
    public String toString() {
        return "Car [brand=" + brand + ", price=" + price + "]";
    }
}

自然排序eg:

package com.edu_06;

import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        //使用自然排序对存储进来的Car对象进行排序
        TreeSet<Car> ts = new TreeSet<Car>();

        //创建汽车对象
        Car c1 = new Car("lanbojini", 1000);
        Car c2 = new Car("tesila", 1000);
        Car c3 = new Car("mashaladi", 2000);

        //存入集合
        ts.add(c1);
        ts.add(c2);
        ts.add(c3);

        //遍历集合
        Iterator<Car> it = ts.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }       
    }
}
package com.edu_06;

public class Car implements Comparable<Car>{
    private String brand;
    private int price;
    public Car(String brand, int price) {
        super();
        this.brand = brand;
        this.price = price;
    }
    public Car() {
        super();
        // TODO Auto-generated constructor stub
    }
    public String getBrand() {
        return brand;
    }
    public void setBrand(String brand) {
        this.brand = brand;
    }
    public int getPrice() {
        return price;
    }
    public void setPrice(int price) {
        this.price = price;
    }
    @Override
    public int compareTo(Car c) {
        int num = this.price  - c.price;
        int num2 = num==0?this.brand.compareTo(c.brand):num;
        return num2;
    }
    @Override
    public String toString() {
        return "Car [brand=" + brand + ", price=" + price + "]";
    }
}

4.Set的遍历
4.1Iterator:
4.2foreach:

5.HashSet与TreeSet的相同点与不同点
相同点:
单列集合,元素不可重复
不同点
1. 底层存储的数据结构不同
HashSet底层用的是HashMap哈希表结构存储,而TreeSet底层用的是TreeMap树结构存储
2.存储时保证数据唯一性依据不同
HashSet是通过复写hashCode()方法和equals()方法来保证的,而TreeSet通过Compareable接口的compareTo()方法来保证的
3.有序性不一样
HashSet无序,TreeSet有序

  • 这种情况的数据,属于一一对应的映射关系。这种关系的集合在java叫Map。
  • Map:将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

  • Map接口中的方法概述(创建集合测试方法):

  • A:删除功能
  • void clear():移除集合中的所有键值对元素
  • V remove(Object key):根据键移除键值对元素,并返回值
  • B:判断功能
  • boolean containsKey(Object key):判断集合中是否包含指定的键
  • boolean containsValue(Object value):判断集合中是否包含指定的值
  • boolean isEmpty():判断集合是否为空
  • C:获取功能
  • Set
package com.edu_07;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MapDemo {
    public static void main(String[] args) {
        //创建一个Map集合
        //键是学号--值是姓名
        Map<Integer,String> map = new HashMap<Integer,String>();

        //V put(K key,V value):集合添加键值对
        map.put(1, "小宁");
        map.put(2, "小纲");
        map.put(3, "小华");
        map.put(4, "小诺");

        //void clear():移除集合中的所有键值对元素
        //map.clear();

        //V remove(Object key):根据键移除键值对元素,并返回值
        //String remove = map.remove(1);
        //System.out.println(remove);


        //boolean containsKey(Object key):判断集合中是否包含指定的键
        //boolean containsKey = map.containsKey(2);
        //System.out.println(containsKey);

        //boolean containsValue(Object value):判断集合中是否包含指定的值
        //boolean containsValue = map.containsValue("周杰伦");
        //System.out.println(containsValue);

        //boolean isEmpty():判断集合是否为空
        //System.out.println(map.isEmpty());

        //int size():键值对对数。
        //System.out.println(map.size());

        //Collection<V> values():获取所有的值
        /*
        Collection<String> values = map.values();
        Iterator<String> it = values.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }*/


        //Set<Map.Entry<K,V>> entrySet():获取键值对对象的集合,遍历键值对对象,
        //利用getKey(),getValue()取出键和值(理解即可)
        Set<Entry<Integer,String>> entrySet = map.entrySet();
        for (Entry<Integer, String> entry : entrySet) {
            System.out.println(entry.getKey()+"  "+entry.getValue());
        }

        System.out.println("--------------------");
        //Set<K> keySet():获取所有的键
        Set<Integer> keys = map.keySet();
        for (Integer key : keys) {
            //V get(Object key):根据键获取值
            System.out.println(key+"  "+map.get(key));
        }       
    }
}

2.HashMap
2.1元素顺序:元素顺序不可预测
2.2底层算法:哈希算法
2.3对键没有要求(仅仅相对于TreeMap来说)
知识点demo演练:
1.存入(String,String)主要讲解遍历方式,键:丈夫 值:妻子

package com.edu_08;

import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;

public class HashMapDemo {
    public static void main(String[] args) {
        // 1.存入(String,String)主要讲解遍历方式,键:丈夫  值:妻子
        HashMap<String, String> hm = new HashMap<String,String>();

        //给键值对集合存入元素
        hm.put("小白", "大白");
        hm.put("小黑", "大黑");
        hm.put("小黄", "大黄");
        hm.put("小伦", "大伦");
        //hm.put("小白", "小洪");,当后面存入的元素和前面的键的值相同的时候,前面的元素的值会被后面的元素的值代替

        //遍历,通过建找值
        Set<String> keys = hm.keySet();
        for (String key : keys) {
            System.out.println(key+"  "+hm.get(key));
        }

        System.out.println("-------------");
        //通过找到结婚证,来分别找到丈夫和妻子
        Set<Entry<String,String>> entrySet = hm.entrySet();
        for (Entry<String, String> entry : entrySet) {
            System.out.println(entry.getKey()+"  "+entry.getValue());
        }       
    }
}

2.存入(String,Student)键:String(国籍) 值:Student

package com.edu_09;

import java.util.HashMap;
import java.util.Set;

public class HashMapDemo {
    public static void main(String[] args) {
        // 2.存入(String,Student)键:String(国籍)  值:Student
        HashMap<String, Student> hm = new HashMap<String, Student>();

        //创建学生对象
        Student s1 = new Student("杰克逊", 60);
        Student s2 = new Student("孙楠", 50);
        Student s3 = new Student("权志龙", 30);

        //将对象存入集合
        hm.put("美国", s1);
        hm.put("中国", s2);
        hm.put("韩国", s3);

        //同过键找值
        Set<String> keys = hm.keySet();
        for (String key : keys) {
            System.out.println(key+"  "+hm.get(key));
        }       
    }
}
package com.edu_09;

public class Student{
    private String name;
    private int age;
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    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 "Student [name=" + name + ", age=" + age + "]";
    }   
}

3.存入(Student,String),键是同一个对象的时候要把之前存入的元素挤出去,想要实现这样的效果的话,
需要重写javabean里面的hashCode()和equals()方法

package com.edu_10;

import java.util.HashMap;
import java.util.Set;

public class HashMapDemo {
    public static void main(String[] args) {
        // 3.存入(Student,String)
        //创建一个Map集合
        HashMap<Student, String> hm = new HashMap<Student, String>();

        //创建学生对象
        Student s1 = new Student("小白", 12);
        Student s2 = new Student("小楠", 14);
        Student s3 = new Student("大白", 18);
        Student s4 = new Student("大白", 18);

        //将对象存入集合
        hm.put(s1, "美国");
        hm.put(s2, "中国");
        hm.put(s3, "韩国");
        hm.put(s4, "中国");

        //遍历集合
        Set<Student> keys = hm.keySet();
        for (Student s : keys) {
            System.out.println(s+"  "+hm.get(s));
        }       
    }
}
package com.edu_10;

public class Student{
    private String name;
    private int age;
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Student() {
        super();
        // TODO Auto-generated constructor stub
    }
    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 "Student [name=" + name + ", age=" + age + "]";
    }
    @Override
    public int 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) {
        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;
    }   
}

3.Treemap
3.1元素顺序:元素顺序与键的排序规则有关
3.2底层算法:Tree算法
3.
知识点demo演练:
1.存入(Integer,String),主要验证排序方式
2.存入(Student,String),键:Student 值:地址

4.遍历(画图进行讲解)
集合遍历:1.获取建的集合 2.遍历键 3.根据键找值foreach()
1.foreach():根据丈夫找妻子(根据键找值)
2.entrySet():(Set

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值