自学Java基础知识第十四天

day14

1. Set集合

1.1 Set集合概述

  1. Set集合是Collection的一个子接口,来自于java.util
  2. Set集合特点:

1) 元素存取不能保证有序

2) 没有索引

3) 不存储重复元素

  1. Set接口, 不能实例化对象, 需要实现类, HashSet哈希表实现结构

代码

package com.ujiuye.set;

import java.util.HashSet;

import java.util.Set;

public class Demo01_Set存储元素不重复 {

public static void main(String[] args) {

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

        set.add(99);

        set.add(1);

        set.add(15);

        set.add(99);

        set.add(1);

        

        System.out.println(set);// [1, 99, 15]

        

        Set<String> set1 = new HashSet<>();

        set1.add("99");

        set1.add("1");

        set1.add("15");

        set1.add("99");

        set1.add("1");

        

        System.out.println(set1);// [99, 1, 15]

}

}

1.2 Set集合的遍历

Set集合中没有特殊方法, 直接使用从Collection父接口重写的方法

  1. toArray() : Set集合中的元素赋值到一个Object[] 数组中,通过遍历数组相当于遍历Set集合中的元素(集合转数组)
  1. toArray(T[] a) : 将集合中的元素赋值到参数T[] 数组中, T类型与集合中的泛型保持一致,

1) 数组a长度大于等于集合中元素的个数, 集合元素直接复制到T[], 返回T[]数组

2) 数组a长度集合中元素的个数, 方法中会自动创建出一个新的T[]数组, 用于复制数据, 将新的T[]进行返回(集合转数组)

  1. 迭代器
  2. 增强for(forEach) : 也是循环

1) 增强for循环语法结构:

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

}

2) 变量名 : 用于表示集合或者数组中的每一个元素

3) 增强for底层实现原理是迭代器, 因此增强for遍历集合同时,如果对于集合进行修改, 也是会报出: 并发修改异常

注意 : 迭代器和增强for都无法获取到元素的索引,因此无法通过索引操作数组或者集合中的元素

遍历1

package com.ujiuye.set;

import java.util.HashSet;

import java.util.Set;

public class Demo02_Set遍历1 {

public static void main(String[] args) {

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

        set.add(99);

        set.add(1);

        set.add(15);

        set.add(99);

        set.add(1);

        

        // 1. set集合转换成Object[]数组

        Object[] objArr = set.toArray();

        // 2. 遍历objArr数组

        for(int index = 0; index < objArr.length; index++) {

         Object obj= objArr[index];

         Integer i = (Integer)obj;

         System.out.println(i);

        }

}

}

遍历2

package com.ujiuye.set;

import java.util.HashSet;

import java.util.Set;

public class Demo03_Set遍历2 {

public static void main(String[] args) {

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

        set.add(99);

        set.add(1);

        set.add(15);

        

        // 1. 创建出一个与set集合泛型一致的数组

        Integer[] arr = new Integer[set.size()];

        set.toArray(arr);

        

        for(int index = 0; index < arr.length; index++) {

         Integer i = arr[index];

         System.out.println(i);

        }

}

}

遍历3

package com.ujiuye.set;

import java.util.HashSet;

import java.util.Iterator;

import java.util.Set;

public class Demo04_Set遍历3 {

public static void main(String[] args) {

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

        set.add(99);

        set.add(1);

        set.add(15);

        

        Iterator<Integer> it = set.iterator();

        while(it.hasNext()) {

         Integer i = it.next();

         System.out.println(i);

        }

}

}

遍历4

package com.ujiuye.set;

import java.util.HashSet;

import java.util.Set;

public class Demo05_Set遍历4 {

public static void main(String[] args) {

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

         set.add("hello");

         set.add("a");

         set.add("world");

         

         // 1. 使用增强for进行set集合遍历

         for(String s : set) {

          System.out.println(s);

         }

}

}

1.3 HashSet保证元素唯一原理

1.3.1 HashSet存储JDK提供类型

  HashSet集合存储数据类型是JDK提供类型, 举例 : Integer, String,Double... , 存储在HashSet集合中, 能保证元素唯一

1.3.2 HashSet存储自定义数据类型

  1. 自定义出一个Person类型, 设计出两个属性 name , age
  2. 将几个Person对象存储在HashSet集合中, 要求: 如果Person对象中的nameage的值都相同, 认为Person类型数据重复, HashSet不存储重复元素;
  3. 存储相同成员变量值的Person对象后, HashSet没有去重复
  4. 查看HashSetadd方法功能 : 发现先调用了对象hashCode方法, 后调用equals方法
  5. 推断, 现在需要将PersonhashCodeequals方法重写, 使用alt + shift + s, 自动生成hashCodeequals方法重写, 重写后Person类型可以根据成员变量的值进行唯一存储机制

代码

package com.ujiuye.set;

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();

}

@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;

}

}

package com.ujiuye.set;

import java.util.HashSet;

public class Demo06_HashSet存储定义类型唯一 {

public static void main(String[] args) {

       HashSet<Person> set = new HashSet<>();

       set.add(new Person("张三",20));

       set.add(new Person("李四",20));

       set.add(new Person("张三",20));

       set.add(new Person("王五",19));

       

       System.out.println(set);     

}

}

1.3.3 hashCodeequals方法

1. hashCode() : 方法从父类Object继承而来, 功能就是获取到对象的哈希码值. 哈希码值是一个整数结果(int)

  a : Object源代码中 : 将一个对象的内存地址转换成一个整数,不同的对象返回不同的整数; 根据对象返回整数值结果是否一致,判断是否是同一个对象

  b : 子类重写hashCode方法, 重写的过程,是将一个对象的成员变量对应的hashCode值计算出来

总结 : hashCode方法就是通过算法比较是否是同一个对象

  1. equals() : 方法从父类Object继承而来

  a : Object源代码中, 比较的是两个对象内存地址是否相等

  b : 重写equals方法, 比较就是两个对象成员变量值是否相等

1.3.4 HashSet保证唯一的原理

 

1.4 LinkedHashSet

1. LinkedHashSet类型是HashSet的子类, 底层维护了双向链表, 元素存入集合的顺序与从集合中取出元素的顺序能保证一致

2. 除了元素存储有序之外, 其他的所有功能包括保证元素唯一的原理,都与HashSet一致

代码

package com.ujiuye.set;

import java.util.HashSet;

import java.util.LinkedHashSet;

public class Demo08_LinkedHashSet {

public static void main(String[] args) {

        HashSet<String> set = new HashSet<>();

        set.add("He");

        set.add("she");

        set.add("it");

        set.add("she");

        set.add("a");

        

        System.out.println(set);// [she, it, He]

        

        LinkedHashSet<String> set1 = new LinkedHashSet<>();

        set1.add("He");

        set1.add("she");

        set1.add("it");

        set1.add("she");

        set1.add("a");

        

        System.out.println(set1);// [He, she, it]

}

}

3. Map集合

3.1 Map集合的概述

  1. Map集合 : 双列集合顶层父接口
  2. map : 英文中表示地图, 地图上的每一个点, 对应现实生活中一个地理位置, 因此地图是表示一对一的关系, Map集合也是数据一对一的关系
  3. Map<K,V> :

K---Key,

  V---Value ,

  因此将Map中的成对的元素称为键值对映射关系, 一对一的关系, 一个Key的值对应一个Value的值

  1. Map集合存储KV特点:

1) Map集合没有索引, 元素存储无序

2) Map集合中, Key的值是唯一的(不重复), Value值可以重复; 通常使用唯一的Key值操作对应的value

3.2 Map集合中的常用方法

Map集合是接口, 接口不能实例化对象, 需要实现类, HashMap, 底层哈希表实现结构

  1. put(K key, V value) :

  a : 如果存入的key的值在Map集合中不存在, 于是put方法表示向Map集合中添加数据

  b : 如果存入的key的值在Map集合中已经存在, put方法相当于修改功能, 存入的value值替换掉原有的value

  1. remove(Object key) : 通过Map中唯一key的值, key和对应的value,键值对映射关系从Map集合中删除, 方法返回被删除的value
  2. clear() : 表示将Map集合中的所有键值对映射关系删除掉, Map集合本身还存在
  3. isEmpty() : 如果Map集合中没有任何键值对元素, isEmpty结果为true, 否则false
  4. size() : 获取Map集合中的键值对数量, 求集合长度
  5. containsKey(Object key) : 验证Map集合的键值中,是否包含参数key, 包含返回true, 不包含返回false
  6. containsValue(Object value) : 验证Map集合的Value值中,是否包含参数value, 包含返回true, 不包含返回false
  7. get(Object key) : 通过参数给出的key,获取到对应的value, 返回值类型为对应V

代码

package com.ujiuye.map;

import java.util.HashMap;

import java.util.Map;

public class Demo01_Map常用方法 {

public static void main(String[] args) {

// Map集合没有索引, Key值不重复, 存储元素无序

        Map<Integer, String> map = new HashMap<>();

        // 1. put

        map.put(2, "b");

        map.put(1, "a");

        map.put(11, "c");

        

        // 2. put

        map.put(11, "end");

        System.out.println(map.size());// 3

        // 6. containsKey

        System.out.println(map.containsKey(19) + "-----");// false

        System.out.println(map.containsKey(11));// true

        // 7. 补充containsValue

        // 8. get(Object key)

        String value11 = map.get(16);

        System.out.println(value11 + "++++++");// null

        

        String value22 = map.get(2);

        System.out.println(value22 + "?????");// b

        

        System.out.println(map);//{1=a, 2=b, 11=end}

        

        // 3. remove

        String value = map.remove(1);

        System.out.println(value);// a

        

        System.out.println(map);// {2=b, 11=end}

        

        // 4. clear

        map.clear();

        System.out.println(map);// {}

        

        // 5. isEmpty

       boolean boo =  map.isEmpty();

       System.out.println(boo);// true

       

       System.out.println(map.size());  //0    

}

}

3.3 Map集合的第一种遍历方式

  1. Map<K,V>集合中有一个方法功能:

   keySet() : 表示将Map集合中的所有的Key的值放置到一个Set<K>集合中

  1. 遍历Set<K>集合, 获取到每一个Key的值, 通过get(Key)获取到对应的value

   

代码

package com.ujiuye.map;

import java.util.HashMap;

import java.util.Map;

import java.util.Set;

public class Demo02_Map第一种遍历KeySet {

public static void main(String[] args) {

Map<Integer, String> map = new HashMap<>();

        map.put(2, "b");

        map.put(1, "a");

        map.put(11, "c");

        

        // 1. 获取到map中的所有key

        Set<Integer> set = map.keySet();

        // 2. 遍历set集合, 获取到每一个key

        for(Integer key : set) {

         // 3. 通过get(Key)获取到对应的value

         String value = map.get(key);

         System.out.println(key + "---->" + value);

        }

}

}

3.4 Map集合的第二种遍历方式

  1. Map集合中有方法功能 :

1) entrySet() : 表示将Map集合中的所有的键值对映射关系放置到一个Set集合中, 返回值类型Set<Map.Entry<K,V>>

2)  Entry : 是Map接口中的内部接口, Entry<K,V> 类型表示Map集合中的每一对元素

3)  因为Entry存在于Map类型内部, 调用方式 Map.Entry<K,V>

4)  遍历Set<Map.Entry<K,V>>, 获取出每一对元素关系, Map.Entry<K,V>

5)  Entry类型中, 有方法功能

   a : getKey() : 获取到键值对关系中的key值

   b : getValue() : 获取到键值对关系中的value值

 

代码

package com.ujiuye.map;

import java.util.HashMap;

import java.util.Map;

import java.util.Set;

public class Demo03_Map第二种遍历EntrySet {

public static void main(String[] args) {

Map<Integer, String> map = new HashMap<>();

        map.put(2, "b");

        map.put(1, "a");

        map.put(11, "c");

        

        // 1. 获取到map集合中所有键值对关系

       Set<Map.Entry<Integer, String>> set =  map.entrySet();

       // 2. 遍历set集合, 获取到每一对映射关系

       for(Map.Entry<Integer, String> entry : set) {

        // 3. 将每一对元素中的keyvalue分别获取到

        Integer key= entry.getKey();

        String value = entry.getValue();

        System.out.println(key + "---" + value);

       }

}

}

3.5 HashMap

  1. HashMapMap接口的实现类, 底层基于哈希表实现
  2. HashMap集合中的key的值不重复, 联想到HashSet中的元素也不重复, 因为HashSet保证元素唯一的实现过程就是依靠HashMap中的key值的唯一的实现过程

 

 

  1. 如果HashMap集合中, key值存储自定义类型, 通过类型中成员变量区分元素的重复与否,需要在自定义类型中重写hashCodeequals两个方法功能(alt + shift + s)
  1. 哈希表结构:

  

3.6 LinkedHashMap

  1. LinkedHashMap HashMap的子类, HashMap功能一致, 因为底层维护了双向链表结构,因此可以实现元素的存取和取出的顺序保持一致

代码

package com.ujiuye.map;

import java.util.HashMap;

import java.util.LinkedHashMap;

import com.ujiuye.set.Person;

public class Demo04_HashMap存储自定义类型 {

public static void main(String[] args) {

         HashMap<Person, String> map = new HashMap<>();

         map.put(new Person("张三",20), "新加坡");

         map.put(new Person("李四",20), "北京");

         map.put(new Person("张三",20), "香港");

         map.put(new Person("王五",20), "东北");

         

         System.out.println(map);

         

         LinkedHashMap<Person, String> map1 = new LinkedHashMap<>();

         map1.put(new Person("张三",20), "新加坡");

         map1.put(new Person("李四",20), "北京");

         map1.put(new Person("张三",20), "香港");

         map1.put(new Person("王五",20), "东北");

         

         System.out.println(map1);

}

}

4.抽象类与接口的使用场景(扩展)

 

原文地址:https://www.cnblogs.com/masterhxh/p/13628940.html