Java两周半速成之路(第十二天)

2024-03-10 09:52

本文主要是介绍Java两周半速成之路(第十二天),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一.泛型(JDK1.5以后出现的机制)

1.泛型由来

为什么会有泛型呢? 通过案例引入 早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。

演示:

import java.util.ArrayList;
import java.util.Iterator;/*在此之前的集合,我们使用的时候,可以传入不同的数据类型的元素。但是,实际开发中,一个集合只能够存储一种数据类型,为了就是将来获取元素处理的时候,处理方式能够统一想一想之前也学习过一种容器,这种容器在定义的时候,就明确了元素的数据类型(数组)现在集合想要模仿使用定义数组时的特点,可以明确一个集合元素的数据类型。java为了实现这样的功能,提供了一个技术给我们使用:泛型语句定义格式:<引用数据类型>泛型的好处:1、消除了程序中大部分的黄色警告2、在获取元素的时候,不需要做向下转型3、限制了集合存储的数据类型,将来处理的方式统一*/
public class ArrayListDemo1 {public static void main(String[] args) {
//        //创建集合对象
//        ArrayList list = new ArrayList();
//
//        //创建元素对象并添加到集合中
//        list.add("java");
//        list.add("hadoop");
//        list.add("hive");
//        list.add("java");
//        list.add("hbase");list.add(12);
//
//        //迭代器遍历
//        Iterator iterator = list.iterator();
//        while (iterator.hasNext()) {
//            String s = (String) iterator.next();
//            System.out.println(s + "--" + s.length());
//        }//加入了泛型创建集合对象//  ArrayList<E>ArrayList<String> list2 = new ArrayList<>(); // 后面的尖括号泛型中的数据类型,根据前面定义时的泛型自动类型推断// String[] arr;//创建元素对象并添加到集合中list2.add("java");list2.add("hadoop");list2.add("hive");list2.add("java");list2.add("hbase");
//        list2.add(12);//迭代器遍历Iterator<String> iterator2 = list2.iterator();while (iterator2.hasNext()) {String s = iterator2.next();System.out.println(s + "--" + s.length());}}
}

2.泛型应用

泛型类

把泛型定义在类上

格式: public class 类名<泛型类型1,…>

注意:泛型类型必须是引用类型

演示:

/*开发代码的时候,写的泛型,将来使用的时候,应该传入一个引用数据类型给到开发时的泛型中接收将类当作参数一样进行传递<>中应该定义一个变量,用于接收将来使用时传入的引用数据类型,有点类似于形式参数就要符合标识符的命名规则如果泛型中只需要接收一个引用数据类型,定义时,只需要写一个大写的字母*/
class Demo2<E> {      // Demo2<Integer>//E在一个类中是唯一的public void fun(E a) {    //IntegerSystem.out.println(a);}}/*泛型类:在开发代码的时候,将泛型写在类上*/
public class FanXingDemo2 {public static void main(String[] args) {Demo2<Integer> demo2 = new Demo2<>();demo2.fun(11);}
}

泛型方法

把泛型定义在方法上

格式:public <泛型类型> 返回类型 方法名(泛型类型 ...)

演示:

class Demo3 {//泛型方法,将来调用时可以传入任意的数据类型,与类上面的泛型无关public <E> void fun3(E a) {System.out.println(a);}
}/*泛型方法:将泛型定义在方法上*/
public class FanXingDemo3 {public static void main(String[] args) {Demo3 s3 = new Demo3();s3.fun3(11);s3.fun3('s');}
}

泛型接口

把泛型定义在接口上

格式:public  interface 接口名<泛型类型1…>

import java.util.ArrayList;
import java.util.List;//如果一个类实现一个接口,这个接口有泛型的话,类定义时,也要有泛型,一般情况下与接口的泛型写法一致
interface Inter<E> {void fun4(E a);
}class InterImtl<E> implements Inter<E> {@Overridepublic void fun4(E a) {System.out.println(a);}
}public class FanXingDemo4 {public static void main(String[] args) {Inter<String> inter = new InterImtl<>();inter.fun4("xuyou");
//        inter.fun4(23);List<String> list1 = new ArrayList<>();list1.add("12");System.out.println(list1);
//        list1.add(12);}
}

3.泛型通配符

第一种:

<?>                     任意类型,如果没有明确,那么就是Object以及任意的Java类

第二种:

? extends E        向下限定,E及其子类

第三种:

? super E            向上限定,E及其父类

演示:

import java.util.ArrayList;
import java.util.Collection;/*开发程序时,泛型的高级用法:泛型通配符<?>任意类型,如果没有明确,那么就是Object以及任意的Java类了? extends E向下限定,E及其子类? super E向上限定,E及其父类*/
class Animal {public void fun() {}
}class Dog extends Animal {
}class Cat extends Animal {}class Demo5<E> {    E: Animalpublic void fun(ArrayList<? super E> e) {System.out.println(e);}
}public class FanXingDemo5 {public static void main(String[] args) {// 向下限定,E及其子类ArrayList<? extends Animal> list1 = new ArrayList<Animal>();ArrayList<? extends Animal> list2 = new ArrayList<Dog>();ArrayList<? extends Animal> list3 = new ArrayList<Cat>();
//        ArrayList<? extends Animal> list4 = new ArrayList<Object>();//E: Animal// ? super E 向上限定Demo5<Animal> d = new Demo5<>();//ddAll(Collection<? extends E> c)// Collection<? extends E> 表示将来应该传入一个Collection集合对象,并且集合中的元素类型是E本身或者是E的子类类型// E: AnimalArrayList<Animal> list4 = new ArrayList<>();ArrayList<Dog> list5 = new ArrayList<>();ArrayList<Cat> list6 = new ArrayList<>();ArrayList<Object> list7 = new ArrayList<>();d.fun(list4);d.fun(list7);
//        d.fun(list5);}
}

 4.常用类型:

E:代表元素(Element)类型,通常在集合中使用,如 List<E>。
K:代表键(Key)的类型,通常在 Map 中使用,如 Map<K, V>。
V:代表值(Value)的类型,通常在 Map 中使用,如 Map<K, V>。
T:代表任意类型(Type),通常在方法中使用,如 public <T> T method(T obj)。
N:代表数字类型,如 Number 类型。
R:代表返回类型,如 public <T> R method(T obj)

二. 增强for循环

1.概述

(1)是用于遍历Collection集合和数组

(2)增强for循环存在的目的,主要适用于替代Collection中的迭代器的。

2.格式

        for(元素数据类型 变量 : 数组或者Collection集合) {   

                        语句体 (使用变量即可,该变量就是元素)

    }

3.注意事项:

                       增强for的目标要判断是否为null

演示:


import java.util.ArrayList;
import java.util.Objects;/*增强for循环:是用于遍历Collection集合和数组的语句定义格式:for(元素数据类型 变量名 : Collection集合/数组){直接使用变量名;}增强for循环存在的目的,主要适用于替代Collection中的迭代器的。*/
public class Demo1 {public static void main(String[] args) {//遍历数组
//        int [] arr = null;int [] arr ={11,22,33,44,55};for (int i : arr) {System.out.println(i);}System.out.println("+++++++++++++++++++++++++++++++++++++++++++");//遍历集合ArrayList<String> list1 = new ArrayList<>();list1.add("nihao");list1.add("xuyou");list1.add("caozei");list1.add("11");for (String s : list1) {System.out.println(s);}}
}

三.静态导入

1.概述:

(1)格式:import static 包名….类名.方法名;

(2)可以直接导入到方法的级别

2.注意事项

(1)方法必须是静态的

(2)如果有多个同名的静态方法,容易不知道使用谁?这个时候要使用,必须加前缀。

四.可变参数

1.概述:指的是方法将来调用时,可以传入若干个指定类型的参数

2.使用场景:定义方法的时候不知道该定义多少个参数时使用

3.注意:

(1)一个方法定义中只能有一个可变参数

(2)如果一个方法有多个参数和可变参数,那么可变参数要最后一个定义

演示:

import java.io.Serializable;
import java.util.Arrays;
import java.util.List;/*可变参数:指的是方法将来调用时,可以传入若干个指定类型的参数注意:1、一个方法定义中只能有一个可变参数2、可变参数必须在参数列表中的最后一个定义*/
public class KeBianDemo {public static void main(String[] args) {//需求1:定义一个方法,求四个int类型值的和System.out.println(getSum(1, 2, 3, 4));//需求2:定义一个方法,传入姓名以及各科分数,求总成绩getSum("小明", 11, 22, 33, 44);}//将来传入若干个int类型的元素值,JVM将其封装到一个数组中,这个数组名叫做arrpublic static int getSum(int... arr) {int scoreSum = 0;for (int i : arr) {scoreSum += i;}return scoreSum;}public static void getSum(String name, int... arr) {int scoreSum = 0;for (int i : arr) {scoreSum += i;}System.out.println(name + " " + scoreSum);}}

五. List集合练习

1.集合的嵌套遍历

import java.util.ArrayList;/*集合的嵌套遍历学校(集合),目前有4个班级 1,2,3每个班级也是一个集合 ArrayList<Student> class = new ArrayList<>();*/
class Student {String name;int age;public Student(String name, int age) {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;}@Overridepublic String toString() {return "name:" + name + ",age:" + age;}
}public class ListTest1 {public static void main(String[] args) {ArrayList<Student> class1 = new ArrayList<>();class1.add(new Student("小1", 18));class1.add(new Student("小2", 14));ArrayList<Student> class2 = new ArrayList<>();class1.add(new Student("小3", 16));class1.add(new Student("小4", 18));ArrayList<Student> class3 = new ArrayList<>();class1.add(new Student("小5", 13));class1.add(new Student("小6", 17));class1.add(new Student("小7", 21));ArrayList<ArrayList<Student>> school = new ArrayList<>();school.add(class1);school.add(class2);school.add(class3);for (ArrayList<Student> clazz : school) {for (Student student : clazz) {System.out.println(student);}}}
}

2.获取10个1-20之间的随机数,要求不能重复  

import java.util.ArrayList;
import java.util.Random;//2.获取10个1-20之间的随机数,要求不能重复
public class ListDemo2 {public static void main(String[] args) {ArrayList<Integer> numberLIst = new ArrayList<>();Random random = new Random();while (numberLIst.size() < 10) {int number = random.nextInt(20)+1;if (!numberLIst.contains(number)) {numberLIst.add(number);}}System.out.println(numberLIst);}
}

3.键盘录入多个数据,以0结束,要求在控制台输出这多个数据中的最大值

import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;/*键盘录入多个数据,以0结束,要求在控制台输出这多个数据中的最大值*/
public class LIstTest3 {public static void main(String[] args) {Scanner sc = new Scanner(System.in);ArrayList<Integer> list = new ArrayList<>();int number = -1;int i = 1;while (number!=0) {System.out.print("请输入第" + i + "个数据:");i++;int number1 = sc.nextInt();if(number1==0){break;}list.add(number1);}//方式一://将集合中的第一个元素默认为最大值Integer maxNumber = list.get(0);for (Integer num : list) {if (num>maxNumber){maxNumber=num;}}System.out.println("最大值为:"+maxNumber);//方式二:利用Collecyions工具类
//        System.out.println("最大值为:"+Collections.max(list));}
}

六.Set接口及其子类HashSet

1.概述

Set(接口) :元素无序且唯一             (无序:存储和取出的顺序不一致)

           --HashSet :   底层数据结构是哈希表,线程不安全的,效率高

2.HashSet

(1)构造方法:

HashSet()         创建一个空的集合

(2)注意:

(1)HashMap实例具有默认初始容量(16)和负载因子(0.75)

(2)HashSet中要想保证元素唯一,就要保证元素类中要重写equals和hashCode方法

演示:

import java.util.HashSet;
import java.util.Objects;/*使用HashSet存储学生对象,当学生对象的姓名和年龄一样的时候,表示是同一个学生,应该要进行去重结论:HashSet中要想保证元素唯一,就要保证元素类中要重写equals和hashCode方法。*/
class Student {String name;int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return age == student.age && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, age);}
}public class HashSetDemo {public static void main(String[] args) {//创建一个HashSet集合HashSet<Student>  studentSet= new HashSet<>();//创建学生对象studentSetStudent student1 = new Student("小明", 12);Student student2 = new Student("小花", 14);Student student3 = new Student("小二", 18);Student student4 = new Student("小李", 22);Student student5 = new Student("小明", 12);//将元素添加到HashSet集合中studentSet.add(student1);studentSet.add(student2);studentSet.add(student3);studentSet.add(student4);studentSet.add(student5);//遍历集合for (Student student : studentSet) {         //此时遍历后的结果并没有去重,原因是底层源码中没有重写equals和hashCode方法,比较的是地址值System.out.println(student);}}
}

 HashSet中的add()方法源码分析:


public class HashSet<E> implements Set<E>{private transient HashMap<E,Object> map;private static final Object PRESENT = new Object();public HashSet() {map = new HashMap<>();}//set1.add("pitaya");public boolean add(E e) {//HashSet中的add方法底层是调用了HashMap中的put方法// e -- student1// PRESENT -- new Object()return map.put(e, PRESENT)==null;}
}public class HashMap<K,V> implements Map<K,V>{public HashMap() {this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted}static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);}public V put(K key, V value) {// key -- "pitaya"// value -- new Object()// 与元素类型中的hashCode方法有关return putVal(hash(key), key, value, false, true);}final V putVal(int hash, K key, V value, boolean onlyIfAbsent,boolean evict) {Node<K,V>[] tab;Node<K,V> p;int n, i;//第一次初始化一个hashTable出来if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;//第一个元素,直接放入到哈希表中if ((p = tab[i = (n - 1) & hash]) == null)tab[i] = newNode(hash, key, value, null);else {Node<K,V> e;K k;//判断待插入的元素与已经在哈希表中的元素//1、哈希值是否一样 元素类.hashCode()方法//2、内容值是否一样 元素类.equals()方法if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))e = p;else if (p instanceof TreeNode)e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);else {for (int binCount = 0; ; ++binCount) {if ((e = p.next) == null) {p.next = newNode(hash, key, value, null);if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1sttreeifyBin(tab, hash);break;}if (e.hash == hash &&((k = e.key) == key || (key != null && key.equals(k))))break;p = e;}}if (e != null) { // existing mapping for keyV oldValue = e.value;if (!onlyIfAbsent || oldValue == null)e.value = value;afterNodeAccess(e);return oldValue;}}++modCount;if (++size > threshold)resize();afterNodeInsertion(evict);return null;}}

3. LinkedHashSet类

1.概述:

(1)为HashSet的子类,底层数据结构是哈希表与双向链表

(2)元素有序唯一,由链表保证元素有序,由哈希表保证元素唯一

2.演示:

/*Collection- List-- ArrayList-- Vector-- LinkedList- Set(接口) 元素无序且唯一-- HashSet 底层数据结构是哈希表,线程不安全的,效率高--子类:LinkedHashSet 底层数据结构是哈希表与双向链表*/
import java.util.LinkedHashSet;public class LinkedHashSetDemo {public static void main(String[] args) {//创建LinkedHashSet集合LinkedHashSet<Integer> set = new LinkedHashSet<>();//添加元素set.add(11);set.add(2);set.add(33);set.add(11);set.add(23);//遍历for (Integer i : set) {System.out.println(i);}}
}

 4.TreeSet类

1.概述:

是set接口实现的具体子类

2.排序方式:

(1)使用元素的自然顺序Comparable<T>对元素进行排序(自然排序)

(2)根据创建 set 时提供的Comparator进行排序(比较器排序)

  如何使用这两种排序具体取决于使用的构造方法

3.TreeSet是如何保证元素的排序和唯一性的:

底层数据结构是红黑树(红黑树是一种自平衡的二叉树)

4.构造方法

5.自然排序:

(1)演示:


import java.util.TreeSet;/*Collection- List-- ArrayList-- Vector-- LinkedList- Set(接口) 元素无序且唯一-- HashSet 底层数据结构是哈希表,线程不安全的,效率高--子类:LinkedHashSet 底层数据结构是哈希表与双向链表-- TreeSet 底层数据结构是红黑树(可排序的),线程不安全,效率高TreeSet中的排序方式有两种:1、自然排序  Comparable2、比较器排序 comparator需求1:使用TreeSet存储字符串对象,并遍历通过观察源码发现,因为我们创建TreeSet集合对象的时候,使用的是无参构造方法所以底层创建TreeMap的时候也是无参构造方法,comparator是null,不走比较器排序走的是自然排序*/
public class TreeSetDemo1 {public static void main(String[] args) {//创建TreeSet集合TreeSet<Integer> treeSet = new TreeSet<>();//添加元素treeSet.add(11);treeSet.add(22);treeSet.add(87);treeSet.add(43);treeSet.add(98);//遍历for (Integer i : treeSet) {System.out.println(i);        //元素从小到大排序}}
}

 (2)实例:创建学生对象,加入到TreeSet集合中,按照年龄从小到大排序输出,要求使用自然排序

演示:

import java.util.TreeSet;/*使用TreeSet集合存储自定义对象Student2(String name,int age)要求:最终要按照年龄从小到大排序,并且当学生的姓名和年龄一样的时候要进行去重我们按照存储字符串一样的逻辑存储自定义对象,运行的时候报错了ClassCastException:com.shujia.day13.Student2 cannot be cast to java.lang.Comparable原因是因为,我们现在使用的时候自然排序方式,需要元素的类实现Comparable接口,才可以进行转型*/
class Student implements Comparable<Student> {String name;int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic int compareTo(Student o) {//显式条件:按照年龄从大到小排序//this -- 待插入的元素//o -- 已经在树中的根int cha = o.age - this.age;return (cha == 0) ? o.name.compareTo(this.name):cha;}
}public class TreeSetDemo2 {public static void main(String[] args) {//创建集合TreeSet<Student> treeSet = new TreeSet<>();//新建学生对象Student student1 = new Student("小一", 9);Student student2 = new Student("小二", 34);Student student3 = new Student("小三", 12);Student student4 = new Student("小四", 6);Student student5 = new Student("小五", 9);//添加元素treeSet.add(student1);treeSet.add(student2);treeSet.add(student3);treeSet.add(student4);treeSet.add(student5);//遍历for (Student student : treeSet) {System.out.println(student);}}
}

上述代码Student类如果没有实现Comparable<>接口,就会报以下错误,原因是我们现在使用的时候自然排序方式,需要元素的类实现Comparable<>接口,才可以进行转型

注意: 重写Comparable<>接口中的compareTo()方法,可以让我们实现元素的排序问题

6.比较器排序:

 在创建TreeSet对象的时候使用匿名内部类Comparator重写compareTo()方法

*比较器排序:public TreeSet(Comparator<? super E> comparator) {this(new TreeMap<>(comparator));}小总结:1、如果要使用自然排序,在创建TreeSet对象的时候,使用无参构造方法,但是要保证元素的类实现Comparable接口,重写compareTo方法。2、如果要使用比较器排序,在创建TreeSet对象的时候,使用有参构造方法,传入一个实现了Comparator接口的子类对象,重写compare方法*/
import java.util.Comparator;
import java.util.TreeSet;class Student1 {String name;int age;public Student1() {}public Student1(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}}public class TreeSetDemo3 {public static void main(String[] args) {//创建集合TreeSet<Student> treeSet = new TreeSet<>(new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {//o1 -- 待插入的元素//o2 -- 已经存在树中的根int cha = o2.age - o1.age;return (cha == 0) ? o2.name.compareTo(o1.name):cha;}});//新建学生对象Student student1 = new Student("小一", 9);Student student2 = new Student("小二", 34);Student student3 = new Student("小三", 12);Student student4 = new Student("小四", 6);Student student5 = new Student("小五", 9);//添加元素treeSet.add(student1);treeSet.add(student2);treeSet.add(student3);treeSet.add(student4);treeSet.add(student5);//遍历for (Student student : treeSet) {System.out.println(student);}}
}

7.自然排序和比较器排序的底层源码:

public class TreeSet<E>{private transient NavigableMap<E,Object> m;private static final Object PRESENT = new Object();public TreeSet() {this(new TreeMap<E,Object>()); // this(..)}public TreeSet(Comparator<? super E> comparator) {this(new TreeMap<>(comparator));}TreeSet(NavigableMap<E,Object> m) {this.m = m;}// treeSet.add(s2);public boolean add(E e) {//TreeSet中add方法底层调用的是TreeMap中的put方法//e -- s2//PRESENT -- new Object()return m.put(e, PRESENT)==null;}
}public class TreeMap{private final Comparator<? super K> comparator;private transient Entry<K,V> root;public TreeMap() {comparator = null;}public TreeMap(Comparator<? super K> comparator) {this.comparator = comparator;}public V put(K key, V value) {// key -- "hadoop"// value -- new Object()Entry<K,V> t = root; // null//如果说是第一个元素插入进来,这个元素就作为红黑树的根保存if (t == null) {compare(key, key); // type (and possibly null) checkroot = new Entry<>(key, value, null); // s1size = 1;modCount++;return null;}int cmp;Entry<K,V> parent;// split comparator and comparable pathsComparator<? super K> cpr = comparator; // null//比较器排序if (cpr != null) {do {parent = t;cmp = cpr.compare(key, t.key);if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}//自然排序else {if (key == null) // s2throw new NullPointerException();@SuppressWarnings("unchecked")Comparable<? super K> k = (Comparable<? super K>) key;do {parent = t; // "java"cmp = k.compareTo(t.key); // 1if (cmp < 0)t = t.left;else if (cmp > 0)t = t.right;elsereturn t.setValue(value);} while (t != null);}Entry<K,V> e = new Entry<>(key, value, parent);if (cmp < 0)parent.left = e;elseparent.right = e;fixAfterInsertion(e);size++;modCount++;return null;}}

8.TreeSet中的排序总结:

1、如果要使用自然排序,在创建TreeSet对象的时候,使用无参构造方法, 但是要保证元素的类实现Comparable接口,重写compareTo方法。

2、如果要使用比较器排序,在创建TreeSet对象的时候,使用有参构造方法, 传入一个实现了Comparator接口的子类对象,重写compare方法。

七.Collection集合继承体系总结:

​​​​​​​

​​​​​​​

 

八.Map接口及其实现子类HasMap

1.概述:

(1)Map集合中的元素是一个键值对

(2)一个键对应一个值,键不允许重复,键是唯一的

(3)值可以发生重复

2.Map接口成员方法(一)

V remove(Object key)                  根据键删除整个键值对,因为键是唯一的,返回键对应的值

V remove(Object key)                              判断集合中是否包含键

boolean containsKey(Object key)                 判断集合中是否包含键

boolean containsValue(Object value)           判断集合中是否包含值

boolean isEmpty()                                        判断集合是否为空

void clear()                                                   清空集合

int size()                                                       获取元素的个数,键值对的个数

演示:


import java.util.HashMap;
import java.util.Map;/*Map集合继承体系:1、Map集合中的元素是一个键值对2、一个键对应一个值,键不允许重复,键是唯一的3、值可以发生重复子类:HashMap<K,V>成员方法:V put(K key,V value)V remove(Object key)void clear()boolean containsKey(Object key)boolean containsValue(Object value)boolean isEmpty()int size()*/
public class MapDemo1 {public static void main(String[] args) {//创建HashMap的对象//HashMap()//构造一个空的 HashMap ,默认初始容量(16)和默认负载系数(0.75)。HashMap<String, Integer> map1 = new HashMap<>();//V put(K key,V value) 向集合中添加一个元素键值对,如果键已经存在集合中,值会进行覆盖处理,返回被覆盖的值System.out.println(map1.put("小王", 19));    //nullSystem.out.println("++++++++++++++++++++++++++++++++++++++++++");System.out.println(map1.put("小王", 33));      //19System.out.println(map1);         //{小王=33}map1.put("小李", 18);map1.put("小帅", 13);map1.put("小七", 12);//V remove(Object key) 根据键删除整个键值对,因为键是唯一的,返回键对应的值System.out.println(map1.remove("小七"));      //12System.out.println(map1);     //{小李=18, 小王=33, 小帅=13}//boolean containsKey(Object key)  //判断集合中是否包含键System.out.println(map1.containsKey("小"));     //false//boolean containsValue(Object value)   //判断集合中是否包含值map1.put("小九",12);System.out.println(map1.containsValue(12));  //true//void clear()          //清空集合
//        map1.clear();
//        System.out.println(map1);     //{}//boolean isEmpty()        //判断集合是否为空System.out.println(map1.isEmpty());//int size() 获取元素的个数,键值对的个数System.out.println(map1.size());}
}

3.与遍历有关的成员方法(二)

Set<K> keySet()              获取所有的键组成一个Set集合返回

Set<K> keySet()              获取所有的键组成一个Set集合返回

Collection<V> values()     获取所有的值组成一个Set集合返回

Set<Map.Entry<K,V>> entrySet()              获取所有的键值对组成一个Set集合返回

演示:


import java.util.Collection;
import java.util.HashMap;
import java.util.TreeSet;/*
成员方法:V get(Object key)Set<K> keySet()Collection<V> values()Set<Map.Entry<K,V>> entrySet()Map集合遍历的方式:1、先获取所有的键,遍历键获取对应的值2、直接获取所有的键值对,遍历每一个键值对,就能够得到每一个键和值*/
public class MapDemo2 {public static void main(String[] args) {HashMap<Integer, String> map = new HashMap<>();map.put(1001,"曹操");map.put(1002,"曹丕");map.put(1003,"曹纯");map.put(1004,"曹叡");map.put(1005,"曹冲");//V get(Object key) 根据键获取值System.out.println(map.get(1001)); //曹操//Set<K> keySet() 获取所有的键组成一个Set集合返回System.out.println(map.keySet());        //[1001, 1002, 1003, 1004, 1005]//Collection<V> values() 获取所有的值组成一个Set集合返回Collection<String> values = map.values();System.out.println(values);             //[曹操, 曹丕, 曹纯, 曹叡, 曹冲]// Set<Map.Entry<K,V>> entrySet()  获取所有的键值对组成一个Set集合返回System.out.println(map.entrySet());     //[1001=曹操, 1002=曹丕, 1003=曹纯, 1004=曹叡, 1005=曹冲]}
}

 4.Map集合遍历的方式:

(1)先获取所有的键,遍历键获取对应的值

(2)直接获取所有的键值对,遍历每一个键值对,再获得每一个键和值

演示:

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*Map集合遍历的方式:1、先获取所有的键,遍历键获取对应的值2、直接获取所有的键值对,遍历每一个键值对,就能够得到每一个键和值*/
public class MapDemo3 {public static void main(String[] args){HashMap<Integer, String> map = new HashMap<>();map.put(1001,"曹操");map.put(1002,"曹丕");map.put(1003,"曹纯");map.put(1004,"曹叡");map.put(1005,"曹冲");//方式一:先获取所有的键,遍历键获取对应的值Set<Integer> keys = map.keySet();for (Integer key : keys) {System.out.println(key+"=="+map.get(key));}System.out.println("---------------------------------------------");//方式二:先获取所有的键值对,遍历键值对获取键和值for (Map.Entry<Integer, String> keyValue : map.entrySet()) {System.out.println(keyValue.getKey()+"=="+keyValue.getValue());}}
}

 九.TreeMap类

1.概述:

(1)TreeMap: 底层数据结构是红黑树

(2)根据创建时调用的构造方法不同,map中的键排序的规则不同

(3)创建TreeMap是无参构造方法的话,将来map中的键是以自然排序

(4)创建TreeMap是有参构造方法,传入Comparator<>接口的实现类对象(匿名内部类的方式)

演示:

import java.util.Comparator;
import java.util.TreeMap;/*TreeMap: 底层数据结构是红黑树根据创建时调用的构造方法不同,map中的键排序的规则不同创建TreeMap是无参构造方法的话,将来map中的键是以自然排序创建TreeMap是有参构造方法,传入Comparator接口的实现类对象(匿名内部类的方式)*/
public class TreeMapDemo1 {public static void main(String[] args) {
//        TreeMap<Integer, String> treeMap = new TreeMap<>();          //自然排序TreeMap<Integer, String> treeMap = new TreeMap<>(new Comparator<Integer>() {          //比较器排序@Overridepublic int compare(Integer o1, Integer o2) {return o1 - o2;}});treeMap.put(1004, "小名");treeMap.put(1005, "小花");treeMap.put(1003, "小王");treeMap.put(1002, "小李");treeMap.put(1001, "小帅");System.out.println(treeMap);     //{1001=小帅, 1002=小李, 1003=小王, 1004=小名, 1005=小花}}
}

注意:所有的包装类都实现了Comparator<>接口,但是我们自己自定义的类必须要手动添加Comparator<>接口。

2.Map集合练习

(1)"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)


import java.util.Set;
import java.util.TreeMap;/*"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)*/
public class TreeMapTest1 {public static void main(String[] args) {TreeMap<Character, Integer> treeMap = new TreeMap<>();String s = "aababcabcdabcde";for (int i = 0; i < s.length(); i++) {char c = s.charAt(i);if (!treeMap.containsKey(c)) {treeMap.put(c, 1);} else {treeMap.put(c, treeMap.get(c) + 1);}}//遍历Set<Character> keys = treeMap.keySet();for (Character key : keys) {
//            System.out.print(key+"("+treeMap.get(key)+")");         //a(5)b(4)c(3)d(2)e(1)}}
}

(2)完成对HashMap嵌套ArrayList的遍历

import java.security.Key;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;/*HashMap嵌套ArrayList每一个人都有一些爱好HashMap<Person,ArrayList<String>>*/
class Person {String name;int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}@Overridepublic StringtoString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}public class TreeMapTest2 {public static void main(String[] args) {//创建学生对象Person person1 = new Person("小明", 23);Person person2 = new Person("小李", 33);Person person3 = new Person("小王", 13);//创建ArrayList集合对象,并添加爱好ArrayList<String> arrayList1 = new ArrayList<>();arrayList1.add("打羽毛球");arrayList1.add("打蓝球");ArrayList<String> arrayList2 = new ArrayList<>();arrayList2.add("养生");arrayList2.add("旅游");ArrayList<String> arrayList3 = new ArrayList<>();arrayList3.add("吃好吃的");arrayList3.add("和小伙伴玩");HashMap<Person, ArrayList> hashMap = new HashMap<>();hashMap.put(person1, arrayList1);hashMap.put(person2, arrayList2);hashMap.put(person3, arrayList3);//遍历Set<Map.Entry<Person, ArrayList>> keyValues = hashMap.entrySet();for (Map.Entry<Person, ArrayList> keyValue : keyValues) {for (Object habby : keyValue.getValue()) {System.out.println("姓名和年龄:"+keyValue.getKey() + " "+"爱好:" + habby);}}}
}

 十.Collections类

1.概述:

   针对集合操作的工具类

2.Collections成员方法

(1)public static <T> void sort(List<T> list)                             对集合排序

(2)public static <T> int binarySearch(List<?> list,T key)       二分查找

(3)public static <T> T max(Collection<?> coll)                     获取最大值

(4)public static void reverse(List<?> list)                              使集合中元素逆序

(5)public static void shuffle(List<?> list)                               将集合中的元素随机打乱

                                                                             这里的shuffle和hadoop中的shuffle不是一个概念

注意:Collections工具类中的synchronizedXxx(xxx)方法可以将线程不安全的类变成线程安全的类,转换后使用方式不变

演示:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;/*Collections工具类可以将线程不安全的类变成线程安全的类,使用方式不变synchronizedXxx(xxx)*/
public class CollectionsDemo2 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();List<String> list1 = Collections.synchronizedList(list);list1.add("java");list1.add("java");list1.add("java");list1.add("java");System.out.println(list1);}
}

这篇关于Java两周半速成之路(第十二天)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/793868

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

在cscode中通过maven创建java项目

在cscode中创建java项目 可以通过博客完成maven的导入 建立maven项目 使用快捷键 Ctrl + Shift + P 建立一个 Maven 项目 1 Ctrl + Shift + P 打开输入框2 输入 "> java create"3 选择 maven4 选择 No Archetype5 输入 域名6 输入项目名称7 建立一个文件目录存放项目,文件名一般为项目名8 确定