java学习-Set和Map集合

1. Set集合

1.1 Set集合介绍

  1. Set集合Collection集合的一个子接口
  2. Set集合特点:

    1) 元素存取无序 : 存储Set集合元素的顺序与从Set集合中取出元素的顺序不能保证一致

    2) 无索引 : Set集合中的每一个元素没有索引位置

    3) 去重复 : Set集合中不存储重复的元素

  3.Set接口,不能实例化对象, 找到实现类HashSet, 哈希表数据结构

     Set<E> set = new HashSet<>();

代码

public class Demo01_Set集合介绍 {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("999");
        set.add("999");
        set.add("a");
        set.add("Hello");
        set.add("a");
        set.add("a");
        
        System.out.println(set);//[a, Hello, 999]
    }
}

1.2 Set集合遍历

  1. toArray() : 将集合中的元素转换到一个Object[] 类型数组中
  2. toArray(T[] arr) : 集合转数组; 但是列表中需要提供一个与集合数据类型相同的数组类型参数, 将集合中元素同步到参数数组中, 这个数组具有指定类型, 遍历数组时候不需要向下转型; 如果arr数组大小不够集合中的元素个数, toArray方法会为你生成一个新的T[]作为方法的返回; 返回值类型T[]
  3. 迭代器
  4. 增强for(forEach) :

    1) forEach语句结构:

     for( 元素数据类型  变量名 : 需要遍历的集合或者数组 ){

    }

  2) 说明 :

     a : 元素数据类型 : 表示需要遍历的这个集合或者数组中的元素具有的数据类型

     b : 变量名 : 表示集合或者数组中的每一个元素

  3) 注意 :

     a : 增强for 语法底层是使用了迭代器的遍历原理

     b : 使用增强for有可能会发生并发修改异常

代码

public class Demo02_Set集合遍历1 {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("999");
        set.add("a");
        set.add("Hello");
        
        Object[] objArr = set.toArray();
        for(int index = 0; index < objArr.length; index++) {
            Object obj = objArr[index];
            String s = (String)obj;
            System.out.println(s);
        }
    }
}
public class Demo03_Set集合遍历2 {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("999");
        set.add("a");
        set.add("Hello");
        
        String[] a = new String[set.size()];
        
        set.toArray(a);
        
         for(int index = 0; index < a.length; index++) {
             String s = a[index];
             System.out.println(s);
         }
    }
}
public class Demo04_Set集合遍历3 {

    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("999");
        set.add("a");
        set.add("Hello");
        
        Iterator<String> it = set.iterator();
        while(it.hasNext()) {
            String s = it.next();
            System.out.println(s);
        }
    }
}
public class Demo05_Set集合遍历4 {

    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("999");
        set.add("a");
        set.add("Hello");
        
        /*for( 元素数据类型  变量名 : 需要遍历的集合或者数组 ){

        }*/
        for(String s : set) {
            System.out.println(s);
            set.add("world");
        }
    }
}

1.3HashSet保证元素唯一原理

  1.3.1 HashSet存储JDK提供类型

   HashSet存储JDK提供的类型时, 可以保证元素存储是去重复的

  1.3.2 HashSet存储自定义类型

  1. 自定义的类Person, Person中具有name和age属性, 如果Person的姓名和年龄都相同,认为这是重复的数据,需要HashSet进行去重复存储
  2. 设计好了Person类型之后,将多个Person对象存储在HashSet中, 发现没有给自定义类型进行去重复
  3. 认为与HashSet中add方法的实现有关, add方法中, 使用了hashCode() 和equals() 方法
  4. 试着将hashCode() 和equals() 方法在Person类型中重写, alt + shift + s , 重写后,去重复成功
  5. 总结 : 自定义类型重写hashCode() 和equals() 方法,保证在HashSet中存储元素唯一

代码

ublic class Person {
    private String name;
    private int 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;
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Person() {
        super();
    }
    @Override
    public String toString() {
        return "Person [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;
        Person other = (Person) 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 Demo07_HashSet存储自定义Person {
   public static void main(String[] args) {
       // 要求 : 如果人员信息, 姓名和年龄都相同,认为Person重复数据
        HashSet<Person> set = new HashSet<>();
        set.add(new Person("张三",20));
        set.add(new Person("李四",20));
        set.add(new Person("张三",20));
        
        System.out.println(set);//[Person [name=李四, age=20], Person [name=张三, age=20]]   
  }
}

  1.3.3 hashCode方法

  1. hashCode方法来自于Object类型中, 可以被所有类继承使用
  2. hashCode源代码在Object中功能: 比较对象是否是同一个

    1) 求对象的哈希码值, 将一个对象在内存中的地址转换成一个整数结果, 这个整数就称为对象的哈希码值

    2) 不同的对象计算出不同的整数(哈希码值), 因为整数结果不同,验证对象是否是同一个

  3.hashCode计算规则:

    1) 同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数

    2) equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果

    3) equals(Object) 方法,两个对象是不相等的, 那么对这两个对象中的每个对象调用 hashCode 方法整数结果尽量不相同

  4.实际开发中, 比较两个对象的地址没有意义, 通过在子类中重写hashCode方法, 重写之后,比较的就是对象中的成员变量对应的hashCode值是否相等

  1.3.4 LinkedHashSet

  1. LinkedHashSet是HashSet的一个子类, 子类中方法与HashSet中的方法一样, 同样也可以保证元素的唯一性
  2. LinkedHashSet 底层结构 : 双向链表, 能够保证添加进入到集合中的元素与从集合中取出的元素顺序一致,保证迭代顺序

代码

public class Demo08_LinkedHashSet {
    public static void main(String[] args) {
        LinkedHashSet<String> linkSet =  new LinkedHashSet<>();
        linkSet.add("999");
        linkSet.add("Hello");
        linkSet.add("a");
        
        System.out.println(linkSet);//[999, Hello, a]
        
        HashSet<String> set = new HashSet<>();
        set.add("999");
        set.add("Hello");
        set.add("a");
        
        System.out.println(set);// [a, Hello, 999]      
    }
}

2. Map集合

2.1 Map集合的介绍

  1. Map是双列集合顶层父接口, 来自于java.util包

     Map<K,V> : 描述的键值对映射关系, 一对一 , 一个Key的值对应1个Value

    K-----Key 键

    V----Value 值

  2.map类比记忆 : map英文中表示地图概念, 地图上的每一个点都对应现实生活中的一个地理位置, 将地图一对一的关系类比成Map集合

  3.Map集合的存储特点:

    1) Map集合中, Key值不重复(唯一)

    2) Map集合中, Value值可以重复

  通常对于Map集合的操作,使用唯一的Key值操作对应的Value的值

  4.Map接口, 不能实例化对象, 需要实现类, HashMap--->哈希表结构

2.2 Map集合中的常用方法

  1. put(K key, V vlue):

    1) 如果添加的key值在Map集合中不存在, 那么表示添加功能, 将键值对映射关系添加到Map集合中, 方法返回值类型V--->value

    2) 如果添加的key值在Map集合中已经存在, 那么表示修改功能, 修改(覆盖)指定key对应的value值

  2.remove(Object key) : 将Map集合中指定key值所对应的键值对映射关系删除, 返回值是value值

  3.clear() : 清空Map集合中的所有元素

  4.size() : 获取Map集合中的键值对数量

  5.get(Object key) : 通过Map集合中的key值, 获取到对应的value

  6.containsKey(Object k) : 验证Map集合的key中,是否包含参数k, 包含返回true, 不包含返回false, 返回值类型boolean

  7.containsValue(Object v) : 验证Map集合的value值中,是否包含参数v, 包含返回true, 不包含返回false, 返回值类型boolean

代码

public class Demo01_Map集合常用方法 {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<Integer, String>();
       // 1. put(K key, V vlue):如果添加的key的值在Map集合中不存在, 那么表示添加功能, 
        // 将键值对映射关系添加到Map集合中, 方法返回值类型V--->value
        map.put(11, "a");
        map.put(12, "b");
        map.put(13, "a");
        System.out.println(map);// {11=a, 12=b, 13=a}
        System.out.println(map.size());// 3
        
        // 2.put(K key, V vlue):如果添加的key的值在Map集合中已经存在, 那么表示修改功能, 修改(覆盖)指定key对应的value值
        map.put(12, "new");
        
        System.out.println(map);// {11=a, 12=new, 13=a}
        
        
        // 3. remove(Object key) : 将Map集合中指定key值, 键值对映射关系删除, 返回就是value值
        String value = map.remove(12);
        System.out.println(value);// new 
        
        System.out.println(map);// {11=a, 13=a}
        
        // 4. clear() : 清空Map集合中的所有元素(成对)
        /*map.clear();
        System.out.println(map);//{}
        
        // 5. size() : 获取Map集合中的键值对数量
        System.out.println(map.size());// 0
*/        
        
        // 6. get(Object key) : 通过Map集合中的key的值, 获取到对应的value
        String value1 = map.get(13);
        System.out.println(value1);// a
        
        // 7.containsKey(Object k) : 验证Map集合的key中,是否包含参数k, 包含返回true, 不包含返回false, 返回值类型boolean
        System.out.println(map.containsKey(11));// true
        System.out.println(map.containsKey(12));// false
        
        // 8.containsValue(Object v) : 验证Map集合的value值中,是否包含参数v, 包含返回true, 不包含返回false, 返回值类型boolean
        System.out.println(map.containsValue("a"));// true
        System.out.println(map.containsValue("b"));// false       
    }
}

2.3Map集合的第一种遍历keySet(掌握)

  1. keySet() : 将Map集合中的所有的Key值获取到, 放置到一个Set集合中
  2. 遍历含有Key值的Set集合, 获取到每一个Key值, 然后通过get(Key), 通过每一个Key值获取到齐对应的Value值

代码

public class Demo02_Map第一种遍历KetSet {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(11, "a");
        map.put(13, "a");
        map.put(12, "b");
        
        // 1. 获取到map中的所有的key的值
       Set<Integer> setK= map.keySet();
       // 2. 遍历setK获取到每一个Key值
       for(Integer key : setK) {
           // 3. 通过get方法获取对应的value值
           String value = map.get(key);
           System.out.println(key + "-----" + value);
       }
       
       Iterator<Integer> it = setK.iterator();
       while(it.hasNext()) {
           Integer key1 = it.next();
           String value1 = map.get(key1);
           System.out.println(key1 + "*******" + value1);
       }
    }
}

2.4 Map集合的第二种遍历entrySet(掌握)

greregegr你

  1.entrySet() : 将Map集合中的所有的键值对关系获取到(成对的数据), 放置到一个Set集合中, Map集合中的每一对数据就是Map.Entry<K,V>类型

  2.遍历装有Map.Entry<K,V>键值对类型的Set集合, 获取到每一对关系

  3.在Map.Entry<K,V>类型中, 有方法能单独获取到一对元素中的key和value

    1) getKey() : 获取到键值对中key值, 返回值类型K

    2) getValue() : 获取到键值对中key值, 返回值类型V

代码

public class Demo03_Map第二中遍历EntrySet {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<Integer, String>();
        map.put(11, "a");
        map.put(13, "a");
        map.put(12, "c");
        
        // 1. 获取到Map集合中所有键值对数据
        Set<Map.Entry<Integer, String>> set = map.entrySet();
        // 2. 遍历set集合, 将每一对映射关系获取到
        for(Map.Entry<Integer, String> entry: set) {
            // 3. 获取到一对关系中的key和value
            Integer key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "?????" + value);
        }
    }
}

2.5 HashMap

  1. HashMap : Map双列集合实现类, 底层哈希表结构
  2. HashMap 集合对于元素的存取无序, Map集合没有索引
  3. HashMap集合中的key值唯一, 保证key值不重复实现原理与HashSet一致

    1) 如果HashMap存储JDK提供类型作为key, 直接保证key不重复

    2) 如果HashMap存储自定义的类型作为key, 要求自定义类型中重写hashCode和equals两个方法

代码

public class Person {
    private String name;
    private int 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;
    }
    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
    public Person() {
        super();
        // TODO Auto-generated constructor stub
    }
    @Override
    public String toString() {
        return "Person [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;
        Person other = (Person) 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 Demo04_HashMap存储自定义类型 {
    public static void main(String[] args) {
        HashMap<Person, String> map = new HashMap<>();
        map.put(new Person("zs",19), "新加坡");
        map.put(new Person("lis",20), "香港");
        map.put(new Person("zs",19), "北京");        
        System.out.println(map);      
    }
}

2.6 LinkedHashMap

  1. LinkedHashMap 是HashMap的子类, 方法功能与HashMap一致, 但是LinkedHashMap维护了双向链表, 效果 : 保证元素的迭代顺序 (元素的存取顺序一致)

代码

package com.ujiuye.map;
import java.util.HashMap;
import java.util.LinkedHashMap;
public class Demo05_LinkedHashMap {
    public static void main(String[] args) {
        HashMap<Integer, String> map = new HashMap<Integer, String>();
        map.put(11, "a");
        map.put(13, "a");
        map.put(12, "c");
        
        System.out.println(map);// {11=a, 12=c, 13=a}
        
        LinkedHashMap<Integer, String> map1 = new LinkedHashMap<Integer, String>();
        map1.put(11, "a");
        map1.put(13, "a");
        map1.put(12, "c");
        
        System.out.println(map1);// {11=a, 13=a, 12=c}
    }
}
posted @ 2020-08-08 16:50  zcb_bai  阅读(209)  评论(0编辑  收藏  举报