Java学习---第六周总结

1. 面试题: int 和 String如何互相转换?

1.1 int—>String

1.1.1 直接拼接

核心代码:

		int i = 25 ;
        String result = ""+i ;// 一个空字符串,拼接int类型的25
        System.out.println("result:"+result);//"25": 字符串类型的25
1.1.2 利用Integer 类型作为中间桥梁:

核心代码:

	int i = 50; 		
	Integer ii = new Integer(i) ;
   String result = ii.toString();//底层调用---->public static String toString(int i) {}
    System.out.println("result2:"+result) ; //"50": 字符串类型的50
1.1.3 直接使用String类的方法: public static String toString(int i){}

核心代码:

 		int i = 22;
	String result = Integer.toHexString(i);
    System.out.println("result3:"+result) ; //"22"

1.2 String—>int

	String s = "300";
1.2.1 通过Integer的构造方法 Integer(String s) + public int intValue()

核心代码:

	Integer i1 = new Integer(s) ;
    int intResult = i1.intValue();
    System.out.println("intResult:"+intResult);//300, int类型的300
1.2.2 Integer类的静态功能:直接转换
	//public static int parseInt(String s)throws NumberFormatException
    //String---long public static long parseLong(String s) throws NumberFormatException
   //其他的String----基本类型:都是通用的方法

核心代码:

	int intResult2 = Integer.parseInt(s) ;
    System.out.println("intResult2:"+intResult2) ; //300

2. Character类

2.1 含义

	Character类是基本数据类型char类型的包装类类型,包含char的值

2.2 构造方法

Character(char value) 参数里面也可以为int----char :将一个字符内容构造成包装类类型

2.3 判断功能(成员 方法)

    public static boolean isDigit(char ch):判断当前ch字符是否为数字
    public static boolean isLowerCase(char ch):判断当前ch字符是否为小写字母字符
    public static boolean isUpperCase(char ch)确定指定的字符是否为大写字符。

3. Date 类

3.1 含义:

	java.util.Date:表示日期格式:精确到瞬间毫秒

3.2 构造方法

    public Date():无参构造方法,获取当前系统时间的日期格式  默认使用当前系统时间
    public Date(long date):将long类型-构造成Date对象:long指定时间毫秒值(与1970年1月1日)

3.3 成员方法

	public long getTime():将Date日期格式----转换成long类型返回自1970年1月1日以来的Date毫秒数

3.4 开发中的实际应用(String 日期文本格式如何和Date格式之间转换)

	在开发中:前后端交互:前端提交的日期数据----->String类型
	但是数据库中存储的时间:Date格式
	 DateFormat是日期/时间格式化子类的抽象类,它以语言无关的方式格式化和分析日期或时间。但是它是一个抽象类,抽象类不能实例化,它提供了更具体的子类SimpleDateFormat进行操作!
3.4.1 Date–>String
java.util.Date对象------  SimpleDateFormat     ------->String 日期文本格式   :格式化过程
      public final String format(Date date)
    yyyy:表示年    2009
    MM:月           07/11
    dd:月中的天     01
    HH:小时数      14  (24小时制)
    mm:分钟数      02
    ss:描述        03
3.4.2 String–>Date
构造方法:public SimpleDateFormat(String pattern):参数为 描述日期和时间格式的一种模式
将String--------------SimpleDateFormat------------------>Date:  解析
 public Date parse(String source) throws ParseException:解析方法,可能出现解析异常,当前字符串开头不能解析就出问题

示例:

public class DateDemo2 {
    public static void main(String[] args) throws ParseException {

        //Date---->String 日期文本
        //创建日期对象:表示当前系统时间
        Date date = new Date() ;

        //创建SimpleDateFormat对象:中间桥梁(格式化/解析 工具)
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") ;
        //  public final String format(Date date)
        String dateStr = sdf.format(date);
        System.out.println(dateStr) ;


        System.out.println("------------------------------------------") ;

        //String文本------->Date日期格式
        String sourc = "2008-5-12" ;
        //当前的SimpleDateFormat的模式必须和字符串文本格式对应!,否则解析出问题了
        //创建SimpleDateFormat对象
       // SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd日" ) ;
        SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd" ) ;
        //public Date parse(String source) throws ParseException:
        Date date2 = sdf2.parse(sourc);
        System.out.println(date2) ;//Mon May 12 00:00:00 CST 2008
    }
}

4. 日历类 Calendar

4.1 含义

    java.util.Calendar:抽象类
    表示的特定一组时间:诸如YEAR,MONTH,DAY_OF_MONTH 等等

4.2 如何实例化

    如果一个类定义为抽象类,那么目的是不让这个类实例化,
    它肯定会有静态功能,返回值它本身!( getInstance())

4.3 静态功能:

	 public static Calendar getInstance()

4.4 成员变量

    public static final int YEAR :public static final int MONTH::角标是从0开始计算, 计算出来+1
    public static final int DATE:月中的日期 和DAY_OF_MONTH同义词
    时分秒:查看API

4.5 成员方法

     public int get(int field):获取当前的日历字段
     public abstract void add(int field,int amount):设置时间偏移量,针对当前日历字段,减去或者添加指定amount(偏移量)

示例:

public class CalendarDemo {
    public static void main(String[] args) {

        //创建日历类对象
        Calendar calendar = Calendar.getInstance();
       // System.out.println(calendar); //很多信息: 需要的是年月日

        //获取年
        //public int get(int field):获取当前的日历字段
        int year = calendar.get(Calendar.YEAR) ;
        int month = calendar.get(Calendar.MONTH) ;
        int date = calendar.get(Calendar.DATE) ;

        System.out.println("当前系统时间日期是:"+year+"年"+(month+1)+"月"+date+"日");

        System.out.println("--------------------------------------------------------") ;

        //5年前的今天
        //给年字段设置偏移量
       /* calendar.add(Calendar.YEAR,-5) ;
        year = calendar.get(calendar.YEAR) ;
        System.out.println("当前系统时间日期是:"+year+"年"+(month+1)+"月"+date+"日");*/

       //5年后的10天前
        calendar.add(Calendar.YEAR,5) ;
        year = calendar.get(calendar.YEAR) ;
        //设置天
        calendar.add(Calendar.DATE,-10) ;
        date = calendar.get(Calendar.DATE) ;
        System.out.println("当前系统时间日期是:"+year+"年"+(month+1)+"月"+date+"日");


        System.out.println("-----------------------------------------------") ;
       // public final void set(int year, int month, int date)设置指定的日历字段

        calendar.set(2022,11,18) ;
        year = calendar.get(Calendar.YEAR) ;
        month = calendar.get(Calendar.MONTH) ;
        date = calendar.get(Calendar.DATE) ;
        System.out.println("设置的日历字段时:"+year+"年"+(month+1)+"月"+date+"日");

    }
}

5. System 类

5.1 System 类的认识

    不能实例化
    里面提供一些标准输入流
    静态字段(常量)
    public static final  InputSteam in ;
 	public static final  PrintStream out ;

5.2 静态功能:

    public static void gc() //手动开启垃圾回收器
    public static void exit(int status)//:参数为0,正常终止JVM
    public static void arraycopy(Object src,int srcPos,Object dest,int destPos, int length)//复制数组
    public static long currentTimeMillis()//:计算当前系统时间毫秒值

例:

public class SystemDemo {
    public static void main(String[] args) {

      //  System.err.println("错误日志输出..");
        //字节输入流
        InputStream in = System.in;

        Scanner sc = new Scanner(in) ;

        System.out.println("请输入一个数据int:");
        int a = sc.nextInt() ;
        System.out.println(a) ;

        System.out.println("--------------------------------") ;

        //字节打印流(输出流一种):字节输出流 OutputStream 父类
        PrintStream ps = System.out ;
        ps.println("helloworld"); //打印内容并换行
        ps.println("javaee");
    }
}

5.2.1 public static void gc() //手动开启垃圾回收器

例:

public class SystemDemo2 {
    public static void main(String[] args) {

        //创建Person类对象
        Person p = new Person("高圆圆" ,42) ;
        System.out.println(p) ;

        p = null ;
        System.gc() ;//手动开启垃圾回收器
    }
}
5.2.2 public static void exit(int status)//:参数为0,正常终止JVM
场景:
    当前while循环和switch语句一块使用
    break,结束switch语句,使用while(true),
    当某个条件满足,结束, System.exit(0) ;
5.2.3 public static long currentTimeMillis()//:计算当前系统时间毫秒值
    很少单独使用,在看程序的执行效率问题(计算时间差值) ;
    io流使用字节流和字符流:
    	分别进行文件读写复制,计算执行效率!
    字节流: 读取图片文件,文本文件.音频文件/视频文件
    字符流: 读文本文件效率高于字节流

5.3 面试题(重点): final,finalize()的区别

	前者关键字,后者方法
    final:状态修饰符
        修饰类,不能被继承
        修饰方法,不能重写
        修饰变量,是一个常量
    finalize():
    当垃圾回收器开启的时候,会调用子类的finalize()方法,来回收没有更多引用的对象!
    一般情况:不需要手动开启回收器,自动回收!
    (Jvm:本质: 至少两条线程:main线程(用户线程),垃圾回收线程...)

6. Random:伪随机数生成器

6.1 构造方法

Random():
	创建随机数生成器,通过它调用功能获取的随机是不同的   (使用无参构造居多)
Random(long seed):
	创建随机数生成器,通过它调用功能,产生随机数值相同的

6.2 成员方法

public int nextInt():
	获取随机数int类型范围
public int nextInt(int n):
	获取0-n之间随机数,不包括n  (重点)

示例:

public class RandomDemo {
    public static void main(String[] args) {
        //创建随机数生成器
        //Random random = new Random(111) ;
        //空参构造
        Random random = new Random() ;

        //for循环:产生10个随机
        for(int x = 0 ;  x < 10 ; x ++){
            //int num = random.nextInt();//取值范围:int类型范围
           // System.out.println(num);
            int num = random.nextInt(30) ;
            System.out.println(num) ;
        }
    }
}

7. Math 类

7.1 java.lang.Math: 数学的运算工具类

​ 功能都是静态的

    public static double abs(double/int a):求绝对值
    public static double ceil(double a):向上取整
    public static double floor(double a):向下取整
    public static double max(double a,double b):获取最大值
    public static double min(double a,double b):获取最小值
    public static double random():[0,1) :获取0,1随机数,不包含1
    public static long round(double a):四舍五入
    public static double sqrt(double a):开正方根
    public static double pow(double a,double b):a的b次幂

示例:

import java.util.Scanner ; //类级别
import  static java.lang.Math.abs ;//方法级别  jdk5以后新特性:静态导入
import  static java.lang.Math.ceil ;//方法级别  jdk5以后新特性:静态导入
//import static 包名.类名.静态方法名;
public class MathDemo {
    public static void main(String[] args) {
       // System.out.println(abs(-100));
        System.out.println(java.lang.Math.abs(-100));
        //当前自定义的方法名如果和静态导入的方法名冲突,只能使用指定的包名.类名.方法名使用!
        abs(20.0);
        System.out.println(ceil(12.56));
        System.out.println(Math.floor(11.34));
        System.out.println(Math.max(10,50));
        System.out.println(Math.min(10,50));
        System.out.println(Math.random()) ;
        System.out.println(Math.round(12.78)) ;
        System.out.println(Math.pow(2,3));
        System.out.println(Math.sqrt(9));
    }
    //自定义了一个功能abs
    public static void abs(double ...a){ //a变量名:未知多少个参数
        System.out.println(a) ;
    }

8. BigDecimal 类

8.1 Java提供这样一个类 BigDecimal:对小数进行精确计算的:

 public BigDecimal(String val) :将数字字符构造成BigDecimal对象

8.2 功能

    public BigDecimal add(BigDecimal augend)求和
    public BigDecimal subtract(BigDecimal subtrahend)相减
    public BigDecimal multiply(BigDecimal multiplicand):乘
    public BigDecimal divide(BigDecimal divisor)除

    除的时候,还可以保留小数的精确位数
    public BigDecimal divide(BigDecimal divisor,int scale, RoundingMode roundingMode)
    参数1:指定的除数
    参数2:保留的有效位数
    参数3:指定舍入模式: ROUND_HALF_UP 四舍五入

示例:

public class BigDecimalDemo {
    public static void main(String[] args) {

       // System.out.println(1.01/2.35);
        //System.out.println(1.01- 0.336);

        BigDecimal bg1 = new BigDecimal("1.01") ;
        BigDecimal bg2= new BigDecimal("10.0") ;
        System.out.println(bg1.divide(bg2));
        System.out.println(bg1.add(bg2));
        System.out.println(bg1.multiply(bg2));
        System.out.println(bg1.subtract(bg2));
        System.out.println("-------------------------") ;        System.out.println(bg1.divide(bg2,2,BigDecimal.ROUND_HALF_UP));
    }
}

9. 选择排序

9.1 核心思想

    使用0角标对应的元素依次和后面角标对应的元素进行比较,小的往前放,第一次比较完毕,最小值出现在最小索引处,依次比较,比较的次数:数组长度-1次

示例:

public class ArrayDemo {

    public static void main(String[] args) {
        //给定一个数组
        int[] arr = {24,68,87,57,13} ;

        System.out.println("排序前:");
        //调用功能
       // String reuslt = Arrays.toString(arr);//工具类
        //System.out.println(reuslt);

        //自己的功能
        printArray(arr) ;

    //抽取了一个方法
    private static void selectSort(int[] arr) {
        for (int x = 0; x < arr.length - 1; x++) {//比较次数
            for (int y = x + 1; y < arr.length; y++) {//遍历后面的元素
                //判断
                if (arr[y] < arr[x]) {
                    int temp = arr[x];
                    arr[x] = arr[y];
                    arr[y] = temp;
                }
            }
        }
    }

    public static void printArray(int[] arr){
        System.out.print("[") ;
        for(int x = 0 ; x < arr.length ; x++){
            if(x == arr.length-1){
                System.out.println(arr[x] +"]") ;
            }else{
                System.out.print(arr[x]+", ");
            }
        }
    }
}

10. 对象数组

	一个数组能够存储对象,对象数组!

11. 集合(重点)

11.1 定义

	集合: 一种 容器,能够存储引用数据类型的容器,长度可变!

11.2 集合体系结构


 	Collection<E>      单例集合的根接口                      		Map<K,V> Key,Value
		List:列表                  Set:哈希表
 
子实现类
    ArrayList,LinkedList,Vector        HashSet  TreeSet ----------->来源于HashMap/TreeMap
    学习的顶层接口---子接口的特有功能---研究子实现类的特点
    Collection集合:
    某些集合允许重复元素(List),而其他集合不允许(Set)。 有些有序和有序无序。
    JDK不提供此接口的任何直接实现,提供了更具体的子接口---->子实现类 间接实现!
    集合的有序性:存储和取出一致!
    无序:存储和取出不一致!

11.3 基本功能

    boolean add(Object e):添加任意类型
    boolean remove(Object o):删除指定的元素
    void clear():暴力删除,将集合中所有元素删除
    boolean contains(Object o):判断集合中是否包含指定的元素
    boolean isEmpty():判断是否为空,不为空,false;空,true
    int size():获取集合的元素数

示例:

public class CollectionDemo {
    public static void main(String[] args) {

        //创建Collection集合对象:接口多态
        Collection  c = new ArrayList() ;
        System.out.println(c) ;
        //boolean add(Object e):添加任意类型
        /**
         * 通过ArrayList的原码
         * public boolean add(E e) {
         *         ensureCapacityInternal(size + 1);  // Increments modCount!!
         *         elementData[size++] = e;
         *         return true;
         *     }
         *     只要添加元素,就返回true
         */
        //System.out.println(c.add("hello"));
        //单独调用
        c.add("hello") ;
        c.add("JavaEE") ;
       // c.add(100) ;//int---Integer
        //c.add(new Object()) ;
        c.add("world") ;
        System.out.println(c) ;

        //boolean remove(Object o):删除指定的元素
        System.out.println(c.remove("hello"));
        System.out.println(c) ;

        //   void clear():暴力删除,将集合中所有元素删除
      //  c.clear();

        // boolean contains(Object o):判断集合中是否包含指定的元素
        System.out.println(c.contains("android")) ;
        System.out.println(c.contains("world")) ;
        //boolean isEmpty():判断是否为空,不为空,false;空,true
        System.out.println(c.isEmpty());
        //int size():获取集合的元素数
        System.out.println(c.size());
        System.out.println(c);
    }
}

11.4 创建集合对象

    集合里面都需要<>: 模拟我们的数组的定义格式,
    数组在定义的时候,就已经明确了数据类型了  String[] str = {"hello","world","javaee",100} //报错

    泛型的写法:
    <引用数据类型> 
    作用:就是将集合的对象的创建工作,将运行时期异常,提前到编译时期,解决程序安全性!

    创建集合对象:
    集合<数据类型>  对象名 = new 子实现类<>() ;jdk7泛型推断
    
    集合的传统遍历:(后边都用不到了,使用forEach等)
    Object[] toArray():将集合转换对象数组

12. 面试题: 集合和数组的区别

1)长度的区别
    数组长度:固定
    集合长度:可变
2)存储数据类型的区别
    数组:既可以存储基本数据类型,而且存储引用数据类型
    int[] arr = new int[5] ;
    Student[] students=  new Student[3] ;
    集合:只能存储引用数据类型
3)存储元素的区别:
    数组:虽然以存储基本数据类型,而且存储引用数据类型,元素类型必须统一
    String[] strArray = {"hello","world","JavaEE",100} ;不行,报错
	举例:水杯中的水
    集合:虽然只能存储引用数据类型,但是可以存储任何引用类型, 没有泛型<>:模拟数组的特点
	举例:水杯中的水兑威士忌,兑可乐...

13. Collection集合

13.1 Collection集合的高级功能

boolean addAll(Collection c):
	添加一个集合中的所有元素
boolean containsAll(Collection c):
	包含一个集合的所有元素 (思考:	 包含一个算包含,还是所有元素)        包含所有算包含
boolean removeAll(Collection c):
	删除一个算删除还是删除所有算删除?    结论:删除一个集合中包含另一个集合中的某个元素,就算删除,返回true

13.2 面试题 boolean retainAll(Collection c):

求集合中的交集元素,boolean的表达式意思是什么?
A集合对B集合求交集,boolean 什么情况true/什么情况下false?

将交集的元素保存A集合中,boolean表达的意思:
	将保存在A集合中的元素是否和之前的元素发生变化
	如果前后发生变化,则返回true;没有变化,则返回false!

示例:

public class CollectionDemo {

    public static void main(String[] args) {

        //创建两个集合
        Collection c1 = new ArrayList() ;
        c1.add("abc1") ;
        c1.add("abc2") ;
        c1.add("abc3") ;
        c1.add("abc4") ;
        c1.add("abc5") ;
        c1.add("abc6") ;
        c1.add("abc7") ;

        Collection c2 = new ArrayList() ;

//        c2.add("abc1") ;
//        c2.add("abc2") ;
//        c2.add("abc3") ;
//        c2.add("abc4") ;
        c2.add("abc5") ;
        c2.add("abc6") ;
        c2.add("abc7") ;
        System.out.println("c1:"+c1) ;
        System.out.println("c2:"+c2) ;
        System.out.println("--------------------------------------") ;

        //boolean addAll(Collection c):添加一个集合中的所有元素
      //  System.out.println("addAll():"+c1.addAll(c2));
        //boolean containsAll(Collection c):包含一个集合的所有元素 (思考:包含一个算包含,还是所有元素) 包含所有
       // System.out.println(c1.containsAll(c2));

        //boolean removeAll(Collection c):删除一个算删除还是删除所有算删除?
//        System.out.println(c1.removeAll(c2));

        //boolean retainAll(Collection c): 求集合中的交集元素,boolean的表达式意思是什么?
       // A集合对B集合求交集,boolean 什么情况true/什么情况下false
        System.out.println(c1.retainAll(c2)) ;

        System.out.println("c1:"+c1) ;
        System.out.println("c2:"+c2) ;
    }
}

13.3 Iterator iterator()

	迭代器:集合专有遍历方式
13.3.1 Iterator:接口功能
 	boolean hasNext() 判断是否有下一个可以迭代的元素 (判断功能)
	Object next():获取下一个可以迭代的元素          (获取功能)

示例:

public class CollectionDemo2 {
    public static void main(String[] args) {
        //创建一个Collection集合,给里面存储字符串数据
        Collection c = new ArrayList() ;

        //添加字符串数据
        c.add("hello") ;
        c.add("world") ;
        c.add("java") ;

        //Iterator<E> iterator():迭代器
        Iterator it = c.iterator();     

        //优化:元素都是自己添加的,后期的元素都是来自数据库中
        //通用 代码:while循环
        while(it.hasNext()){
            //System.out.println(it.next()) ;
            //Object obj = it.next();//里面存储的String  Objecg obj = new String() ;
            //获取元素的同时,获取字符串长度

            String s = (String) it.next();
            System.out.println(s+"---"+s.length());
        }
    }
}

示例: 使用Collection存储5个学生,并使用迭代器进行遍历 ,通过getXXX()获取学生的姓名和年龄…

public class Student {
...
}

public class CollectionTest {
    public static void main(String[] args) {
        //创建一个Collection集合
        Collection c = new ArrayList() ;

        //创建5个学生对象
        Student s1 = new Student("亚索",30,"男") ;
        Student s2 = new Student("盲僧",25,"男") ;
        Student s3 = new Student("德邦",22,"男") ;
        Student s4 = new Student("德玛西亚",35,"男") ;
        Student s5 = new Student("咔沙",22,"女") ;
            c.add(s1) ;
            c.add(s2) ;
            c.add(s3) ;
            c.add(s4) ;
            c.add(s5) ;
            //获取迭代器
            Iterator it = c.iterator();//本质就是:接口多态 Iterator it = new Itr() ;//内部类
            while(it.hasNext()){
            //类转换异常
            //java.lang.ClassCastException: com.qf.collection_01.Student cannot be cast to java.lang.String
            //String s = (String)it.next();
           // System.out.println(s) ;
            Student s = (Student) it.next();
            System.out.println(s.getName()+"----"+s.getAge()+"----"+s.getGender());
        }
    }
}

14. List集合

14.1 List定义

	List<E>是Collection的子接口,有Collection大部分功能,但是它自己有功能

14.2 List集合特点:

    有序:存储和取出一致
    元素可以重复!

14.3 List接口特有功能:

    void add(int index, Object element):在指定位置处添加一个新的元素
    Object remove(int index):删除指定位置处的元素
    E set(int index, Object element):修改指定位置处的元素内容
    Object get(int index):获取指定位置处的元素
    ListIterator<E> listIterator():列表迭代器

14.4 List集合的遍历方式有几种?

public class ListDemo {
    public static void main(String[] args) {

        //创建List集合对象
        List<String> list = new ArrayList<>() ;

        //添加元素
        list.add("hello") ;
        list.add("world") ;
        list.add("javaee") ;

        // void add(int index, Object element):在指定位置处添加一个新的元素
        list.add(2,"鸿蒙系统") ;
        // Object remove(int index):删除指定位置处的元素
        System.out.println(list.remove(1)) ;

        // Object set(int index, Object element):修改指定位置处的元素内容
        System.out.println(list.set(1,"Android"));

        // Object get(int index):获取指定位置处的元素
        System.out.println(list.get(0));
        System.out.println(list.get(1));
        System.out.println(list.get(2));
        System.out.println(list) ;

        System.out.println("-----------------------------------") ;

方式1:

	Collection集合的toArray()----Object[]
 Object[] objects = list.toArray();
        for(int x = 0 ; x < objects.length ;x ++){
            String s = (String) objects[x];
            System.out.println(s+"----"+s.length());
        }

方式2:

	Coillection集合的Iterator迭代器
 Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            String s = iterator.next() ;
            System.out.println(s+"----"+s.length());
        }

方式3:

	get(int index) + size() 的普通for循环
 for(int x = 0 ; x < list.size(); x++){
            String s = list.get(x);
            System.out.println(s+"----"+s.length());
        }
    }
}
14.5 ListIterator listIterator():列表迭代器
14.5.1 ListIterator接口
    ArrayList内部类ListItr,(父类:ArrayList的内部类Itr)实现它里面的方法
    boolean hasNext() :判断当前列表中是否下一个可以遍历的元素
    Object next():获取下一个元素
    boolean hasPrevious():判断当前列表中是否有时上一个可以遍历的元素
    Object previous():获取上一个元素

 	 !!!  前提条件:必须有正向遍历,才能使用反写遍历;

示例:

public class ListDemo2 {
    public static void main(String[] args) {

        //创建List存储字符串数据并正向遍历:使用列表迭代器
        List<String> list = new ArrayList<>() ;

        //添加字符串
        list.add("hello") ;
        list.add("world") ;
        list.add("javaee") ;
        list.add("鸿蒙") ;

        //ListIterator<E> listIterator():列表迭代器
       ListIterator<String> lit = list.listIterator(); //它的成员内部类:ListItr类继承内部类Itr  实现ListIterator()
        while(lit.hasNext()){
            String s = lit.next();
            System.out.println(s);
        }
        System.out.println("-----------------------------") ;
      /*  while(lit.hasPrevious()) {
            String s = lit.previous();//获取上一个元素
            System.out.println(s);
        }*/
    }
}

15. jdk5以后提供了特性:增强for循环

15.1 作用

	替代迭代器的Iterator,简化书写方式

15.2 格式:

	for(泛型数据类型 变量名 : 集合对象名称){  //增强for循环 遍历数组非常少,主要用在集合中
           输出变量名;
       }
 
       前提条件:集合对象不能为null,否则就出现空指针异常
 
       目的:替代迭代器!

示例:

public class ForEachDemo {
    public static void main(String[] args) {

        //创建一个数组
        int[] arr = {11,22,33,44,55} ;
        for(int x = 0 ; x < arr.length ; x ++){
            System.out.println(arr[x]);
        }
        System.out.println("-----------------------------") ;
        for(int i :arr ){
            System.out.println(i);
        }

        //主要用在集合中
        List<String> list = new ArrayList<>() ;

        list.add("hello") ;
        list.add("world") ;
        list.add("javaee") ;
        list.add("android") ;
//        list = null ;
        //迭代器
       /* Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            String s = iterator.next();
            if("world".equals(s)){
                list.add("php");
            }
        }*/
        /**
         *  for(泛型数据类型 变量名 : 集合对象名称){  //增强for循环 遍历数组非常少,主要用在集合中
         *  *          输出变量名;
         *  *      }
         */
        for(String s:list){
           /* if("world".equals(s)){
                list.add("php");
            }*/
            System.out.println(s);
        }
    }
}

15.3 并发修改异常

	java.util.ConcurrentModificationException

原因:

    这个异常说明: 当一个集合的元素正在遍历,给集合中添加或者删除元素(修改),迭代器不知道!

    并发:在一个时间点上,当前多个线程同时去操作同一个元素(共享),造成访问冲突!
    一个线程正在遍历集合,另一个线程不能修改集合!

解决方案:

    1)使用集合判断,使用集合添加或者修改
    2)使用迭代器,使用迭代器添加/修改...

15.4 使用List存储多个字符串,有重复元素,如何去重!

15.4.1 新建集合思想
    1)创建一个List集合对象,给里面添加重复元素
    2)创建一个新的List集合,
    3)将以前的集合的元素遍历出来,使用集合对象判断,如果新集合中不包含这个元素,说明不重复,添加新集合中
    4)遍历新集合

注意:

    集合的contains(Object obj)底层依赖于equals方法,而String类型
    已经重写了equals,比较是内容是否相同;
    
    所以如果使用List<自定义类型>,去重,必须保证,当前自定义类型重写Object的hashCode()和equals()
    例: 创建一个List集合对象,给里面添加重复Student元素List<Student> :姓名和年龄一致,认为是同一个人 (新建集合思想)
    Student 这个自定义类,就必须重写Object类的hashCode()和equals()

示例:

public class ListTest2 {
    public static void main(String[] args) {

        //创建List集合对象
        List<String> list = new ArrayList<>() ;

        list.add("hello") ;
        list.add("world") ;
        list.add("javaee") ;
        list.add("hello") ;
        list.add("world") ;
        list.add("world") ;
        list.add("hello") ;
        list.add("javaee") ;     

        //创建一个新的集合
        List<String> newList = new ArrayList<>() ;
        //遍历旧集合获取每一个元素:增强for
        for(String s:list){
       //在新集合中判断是否包含这个元素,如果不包含,才给新集合中添加
            if(!newList.contains(s)){
                newList.add(s) ;
            }
        }
        //遍历新集合
        for(String s:newList){
            System.out.println(s);
        }
    }
}
15.4.2 利用选择排序的业务思想:
	前面的元素依次和后面的元素比较,如果一致,将后面的元素删除掉!

示例:

public class ListTest3 {
    public static void main(String[] args) {
        //创建List集合对象
        List<String> list = new ArrayList<>() ;

        list.add("hello") ;
        list.add("world") ;
        list.add("javaee") ;
        list.add("hello") ;
        list.add("world") ;
        list.add("world") ;
        list.add("hello") ;
        list.add("javaee") ;
       
        //选择排序的核心代码
        for(int x = 0 ; x < list.size()-1; x++){
            for(int y = x+1 ; y < list.size() ; y ++){
       //业务思想:如果前面的元素和后面元素一致,将后面的重复元素删除掉
                if(list.get(y).equals(list.get(x))){
                    //将后面的元素删除
                    list.remove(y) ;
                    y -- ; //减去一个元素,索引值就要变小
                }
            }
        }
        //遍历当前这个集合
        for(String s :list){
            System.out.println(s);
        }
    }
}

16. Generic 泛型

16.1 定义

    使用<引用数据类型>
    集合对象的创建同时明确数据类型,并且将运行时期异常提前到了编译时期(模拟数组定义)

16.2 泛型的好处:

1)提高程序安全性
2)解决黄色警告线
3)使用集合的迭代器避免强转类型强转类型转换

示例: 使用Collection存储字符串数据并遍历

public class GenericDemo {

    public static void main(String[] args) {
        //  使用Collection存储字符串数据并遍历
        Collection<String> c = new ArrayList<>() ; //后面的<可以写上,也可以不写> jdk7以后泛型推断:默认的认为前后类型一致!

        //添加字符串数据
        c.add("hello") ;
        c.add("world") ;
        c.add("Javaee") ;
        //c.add(100)  ; //Integer类型
        //System.out.println(c);

        //获取迭代器Iterator<E>
        Iterator<String> it = c.iterator();
        while(it.hasNext()){
            String s = it.next();
            System.out.println(s+"----"+s.length());
        }
    }
}

16.3 泛型定义再方法上

示例: 提供几个成员方法,成员方法形式参数可以传递任何数据类型

//public class ObjectTool<T> {//泛型定义在类上
public class ObjectTool {//将泛型定义在方法上

    /*public void show(String str){
        System.out.println(str) ;
    }
    public void show(Integer i){
        System.out.println(i) ;
    }
    public void show(boolean b){
        System.out.println(b) ;
    }*/

    /**
     * 泛型定义在方法上的格式:权限修饰符 <T> 返回值类型 方法名(T 参数名){...}
     * 固定格式  T--->Type 任何类型
     */
    public <T> void show(T t){
        System.out.println(t) ;
    }
}

public class ObjectToolTest {
    public static void main(String[] args) {

        //创建ObjectTool类的对象
       /* ObjectTool ot = new ObjectTool() ;
        ot.show("hello") ;
        ot.show(100) ;
        ot.show(true) ;
*/
        //既然形式参数可以是任何数据类型,泛型可以定义类上

        //创建对象
       /* ObjectTool<String> ot = new ObjectTool<>() ;
        ot.show("hello") ;
        ObjectTool<Integer> ot2 = new ObjectTool<>() ;
        ot2.show(100) ;
        ObjectTool<Boolean> ot3= new ObjectTool<>() ;
        ot3.show(true) ;*/

       //难道优化这个show方法必须在类上加入泛型吗?
        //可以,直接将泛型定义在方法上
        ObjectTool ot = new ObjectTool() ;
        ot.show("高圆圆") ;
        ot.show(100) ;
        ot.show(true) ;
        ot.show(12.56);
    }
}

16.4 将泛型定义在接口上

两种情况:

    1)接口的子实现类已经明确了类型
    2)接口的子实现类不明确里面存储的类型
public interface Inter<T> {

    void show(T t) ;
}
16.4.1 情况1: 接口的子实现类已经明确了类型
public class InterImpl<String> implements Inter<String> {
    @Override
    public void show() {
        System.out.println("show InterImpl...");
    }
}
16.4.2 情况2:子实现类不明确泛型的类型(T: Type)
public class InterImpl<T> implements Inter<T>{

    @Override
    public void show(T t) {
        System.out.println(t) ;
    }
}
16.4.3
 Collection<String> c = new ArrayList<>() ;
//一旦明确了泛型,集合添加只能当前类型,能否直接添加Integer? 
//直接添加不了,后期通过反射!
        c.add("hello") ;
        c.add("world") ;
        //c.add(100) ;(String泛型, 目前不能直接添加Integer类型)
16.5 泛型的通配符(了解)
    <?>:代表Object或者任意的Java类型(jdk提供/自定义的)
    <? extends E>:向下限定,E这个类型以及 它的子类
    <? super E> :向上限定 E这个类以及它的父类

17. hashSet集合的添加功能

	add方法
    间接依赖于的HashMap的put方法----->底层依赖于hashCode()和equals()方法
    首先,要比较当前存储String类型数据的哈希码值是否相同,如果相同,
    比较是内容是否一样,调用equals()方法,String类型已经重写了Object,比较内容!	

18. List集合三个子实现类的特点:

	当一些需求没有明确提示使用什么类型的时候,都是用ArrayList(单线程程序中)

18.1 ArrayList:

    底层数据结构是数组,数组的特点:查询快,增删慢
    查询的:通过整数索引,立即查询到元素

    从线程角度考虑:由于实现是不同步的,执行效率高,线程不安全!
    默认容量大小:10个
    扩容机制:1.5倍方式扩容
18.1.1 ArrayList构造方法:
    public ArrayList():构造一个初始容量为十的空列表。
    public ArrayList(int initialCapacity):指定容量大小

18.2 Vector:

    底层数据结构是数组,查询快,增删慢
    线程角度:实现同步的,里面的成员方法大部分都会有synchronized同步锁,保证安全性
    安全性很高,但是执行效率低,单线程程序中,使用ArrayList替代Vector
18.2.1 Vector集合
	在List集合中最明显的特点:线程安全

应用场景:
	如果环境是多线程环境,而且使用集合存储数据,保证线程安全,Vector集合!
18.2.2 目前为止:线程安全的类(多线程中使用)
    StringBuffer/Vector/
   
   线程安全的方法:
    Collections:针对集合操作工具类
    public static <T> List<T> synchronizedList(List<T> list):保证列表同步(安全方法)
18.2.3 Vector集合特有功能:
    public void addElement(Object obj):添加元素
    public boolean removeElement(Object obj):直接从Vector集合中删除指定的元素
    public Object elementAt(int index):通过指定的索引值获取元素------类似于List集合中 get(int index)
    public Enumeration<Object> elements():(特有迭代器)获取Vector集合中的枚举组件接口  ----->类似于  public Iterator iterator():迭代器
     boolean hasMoreElements()  ---->类似于   boolean hasNext() 判断是下一个遍历的元素
     Object nextElement()     --->类似于    Object next()     获取下一个元素

示例:

public class VectorDemo {

    //"main"---->"用户线程"(主线程..)
    public static void main(String[] args) {


        //创建Vector集合,存储字符串数据
        Vector<String> v = new Vector<>() ;

        // public void addElement(Object obj):添加元素
        v.addElement("hello") ;
        v.addElement("world") ;
        v.addElement("javaEE") ;
        v.addElement("mysql") ;
        v.addElement("jdbc") ;
        System.out.println(v);
        // public boolean removeElement(Object obj):直接从Vector集合中删除指定的元素
       // System.out.println(v.removeElement("jdbc"));
       // System.out.println(v);

        //Vector集合遍历:7种   使用特有功能: public Object elementAt(int index) +size()
        for(int x = 0 ; x < v.size() ; x ++){
            String s = v.elementAt(x);
            System.out.println(s) ;
        }

        System.out.println("------------------------------------") ;
        /**
         * public Enumeration<Object> elements():(特有迭代器)获取Vector集合中的枚举组件接口  -----类似于  public Iterator iterator():迭代器
         *                      boolean hasMoreElements()  ---->类似于   boolean hasNext() 判断是下一个遍历的元素
         *                          Object nextElement()     ---类似于    Object next()     获取下一个元素
         */
        Enumeration<String> en = v.elements();
        while(en.hasMoreElements()){
            String s = en.nextElement();
            System.out.println(s) ;
        }
    }
}

18.3 LinkedList

    底层数据结构是一个链表,
    线程角度:  不同步的,单线程中执行效率高,安全性低!

    链表:数据域和指针域组成!
18.3.1 LinkedList特有功能
    public void addFirst(Object e):在链表开头插入元素
    public void addLast(Object e):将元素追加到链表的末尾
    public Object getFirst():获取链表的第一个元素
    public Object getLast():获取链表的最后一个元素
    public Object removeFirst():删除链表第一个元素并获取第一个元素
    public Object removeLast():删除链表最后一个元素并获取

18.4 List集合嵌套应用

18.4.1 格式
	ArrayList<ArrayList<Student>> 
18.4.2 示例:
需求:
    有3个Java基础班,每一个班级都看成一个ArrayList<Student>,
    这个三个班级组成了一个大的集合ArrayList<ArrayList<Student>>
    获取出每一个班级的学生的姓名和年龄;
分析:
    0)创建出大的集合
    1)三个小集合:ArrayList<Student>,添加几个学生数据
    2)分别将三个小集合都添加到集合中
    3)遍历大集合中
     遍历小集合,分别获取信息
class Student{
    ...
}

public class ArrayListTest {
    public static void main(String[] args) {

        //创建出大的集合
        ArrayList<ArrayList<Student>> bigArray = new ArrayList<>() ;

        //第一个Java基础班
        ArrayList<Student> firArray = new ArrayList<>() ;
        //创建3个学生
        Student s1  = new Student("唐僧",50) ;
        Student s2  = new Student("孙悟空",44) ;
        Student s3  = new Student("猪八戒",40) ;
        //添加数据
        firArray.add(s1) ;
        firArray.add(s2) ;
        firArray.add(s3) ;

        //添加到大集合中
        bigArray.add(firArray) ;

        //第二个Java基础班
        ArrayList<Student> secArray = new ArrayList<>() ;
        //三个学生
        Student s4  = new Student("宋江",40) ;
        Student s5  = new Student("武松",35) ;
        Student s6  = new Student("鲁智深",32) ;
        secArray.add(s4) ;
        secArray.add(s5) ;
        secArray.add(s6) ;

        bigArray.add(secArray) ;

        //第三个Java基础班
        ArrayList<Student> thirdArray = new ArrayList<>() ;
        Student s7  = new Student("曹操",45) ;
        Student s8  = new Student("刘备",36) ;
        Student s9  = new Student("周瑜",33) ;
        thirdArray.add(s7) ;
        thirdArray.add(s8) ;
        thirdArray.add(s9) ;

        bigArray.add(thirdArray) ;

        //遍历 ArrayList<ArrayList<Student>>
        for(ArrayList<Student> array :bigArray){
            for(Student s :array ){
                System.out.println(s.getName()+"\t"+s.getAge());
            }
        }
    }
}

19. TreeSet实现自然排序

    TreeSet的无参构造方法:就是要实现自然排序,前提条件:如果是自定类型,那么自定义类型必须实现Comparable接口(自然排序)
    重写compareTo()方法,实现自己的业务排序!

20. Set 集合

20.1 set集合特点

    无序: 存贮和取出不一致;
    保证元素唯一!

20.2 代表: HashSet子实现类

    底层一个HashMap的实例,保证元素唯一(底层哈希表,和HashMap有关系),不能保证迭代顺序恒久不变!
20.2.1 需求: HashSet,并遍历
public class HashSetDemo {
    public static void main(String[] args){
        //创建HashSet集合对象
        Set<String> set = new HashSet<>() ;

        //添加字符串数据
        set.add("hello") ;
        set.add("hello") ;      
        set.add("java") ;
        set.add("java") ;    
        set.add("world") ;
        set.add("world") ;    
        set.add("android") ;
        set.add("android") ;
        set.add("php") ;

        //遍历
        for(String s:set){
            System.out.println(s);
        }
    }
}
20.2.2 需求(去重,重写hashCode和equals)
    使用HashSet存储自定义对象,并保证元素唯一!
    HashSet<Studuent>----9个学生(成员信息:姓名,年龄相同的值),去重!
	分析: Student是自定义类, 所以要实现去重,必须重写Hashcode和Equals 两个方法.
classS Student{
	...
	//重写eqlas和hashCode方法(alt+enter键一键重写)
	@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name.equals(student.name);
    }

    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + age;
        return result;
    }
}
public class HashSetTest {
    public static void main(String[] args) {

        //创建HashSet集合对象
        HashSet<Student> hs = new HashSet<>() ;

        //创建几个学生对象
        Student s1  = new Student("高圆圆",42) ;
        Student s2  = new Student("高圆圆",42) ;
        Student s3  = new Student("高圆圆",35) ;
        Student s4  = new Student("刘诗诗",32) ;
        Student s5  = new Student("刘诗诗",32) ;
        Student s6  = new Student("文章",35) ;
        Student s7  = new Student("文章",35) ;
        Student s8  = new Student("张译",37) ;
        Student s9  = new Student("张译",37) ;

        hs.add(s1) ;
        hs.add(s2) ;
        hs.add(s3) ;
        hs.add(s4) ;
        hs.add(s5) ;
        hs.add(s6) ;
        hs.add(s7) ;
        hs.add(s8) ;
        hs.add(s9) ;

        for(Student s: hs){
            System.out.println(s.getName()+"---"+s.getAge());
        }
    }
}

20.3 子实现类 TreeSet

    TreeSet<E>:底层依赖于TreeMap -----Red-Black-Tree:数据结构:红黑树(自平衡的二叉树结构)
    有两种排序:自然排序/比较器排序,取决于你的构造方法!
20.3.1 特点(自然排序,重写CompareTo方法)
现在使用TreeSet<Integer>,添加一些元素,遍历这个集合,有什么特点呢?
	
	能够将元素自然升序排序!,因为jdk提供的大部分常用类Integer类已经实现Comparable接口,实现了compareTo()    
20.3.2 如果存储Student呢?

分析:

    public TreeSet()构造一个新的,空的数组,根据其元素的自然排序进行排序。
需求:
    使用TreeSet集合存储Student,但是问题,没有排序条件:就报错!

解决方案:
    要实现自然排序,你当前的存储对象的类型必须实现Comparable接口

排序条件:
    1)给定主要条件,自己分析,次要条件!

    使用TreeSet集合存储Student
    主要条件:
    需要按照年龄从小到大排!
    次要条件: 
    年龄一致,判断姓名是否相同.
class Student{
	...
	//重写eqlas和hashCode方法
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        if (age != student.age) return false;
        return name.equals(student.name);
    }
    @Override
    public int hashCode() {
        int result = name.hashCode();
        result = 31 * result + age;
        return result;
    }

    //重写compareTo 方法
    @Override
    public int compareTo(Student s) { //需要后面的元素的年龄和当前根节点元素年龄的比较
        //三元运算
        int num = this.age - s.age ;
        //次要条件:年龄如果相等,不一定就是同一个人,比较姓名的内容是否相同
        int num2 = (num==0)?(this.name.compareTo(s.name)):num ;
        return num2;
}
}
public class TreeSetDemo2 {
    public static void main(String[] args) {

        //创建TreeSet集合对象
        TreeSet<Student>  ts = new TreeSet<>() ; //无参构造方法 :自然排序:Comparable接口

        //创建一些学生
        Student s1 = new Student("gaoyuanyuan",22) ;
        Student s9 = new Student("gaoyuanyuan",22) ;
        Student s2 = new Student("liushishi",35) ;
        Student s3 = new Student("zhaoyouting",20) ;
        Student s4 = new Student("wenzhang",40) ;
        Student s5 = new Student("liudehua",65) ;
        Student s6 = new Student("chenglong",70) ;
        Student s7 = new Student("zhouxingchi",60) ;
        Student s8 = new Student("linqingxia",60) ;

        //添加
        ts.add(s1) ;
        ts.add(s2) ;
        ts.add(s3) ;
        ts.add(s4) ;
        ts.add(s5) ;
        ts.add(s6) ;
        ts.add(s7) ;
        ts.add(s8) ;
        ts.add(s9) ;

        //遍历
        for(Student s :ts){
            System.out.println(s.getName()+"---"+s.getAge());
        }
    }
}
20.3.3 TreeSet集合的另一种排序:比较器排序
    public TreeSet(Comparator<? super E> comparator):实现一个比较器排序
    Comparator<T> 接口中有一个抽象方法
    int compare(T o1,T o2)

需求:

使用TreeSet<Student>,存储学生,按照学生的年龄从小到大排序,并且使用比较器排序
public class TreeSetDemo {
    public static void main(String[] args) {

        //创建TreeSet-->public TreeSet(Comparator<? super E> comparator):实现一个比较器排序

        //方式1:将Comparator的子实现类定义出来(不推荐)

        //如果方法的形式参数如果是接口:实际传递需要接口的子实现类对象(匿名内部类的本质)
        //Comparator<Student> comparator = new MyComparator() ;
        //TreeSet<Student> ts = new TreeSet<>(comparator) ;

        //方式2:接口的匿名内部类:推荐方式
        TreeSet<Student> ts = new TreeSet<>(new 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 ;
            }
        }) ;

        //jdk8特性:lambda----->
        // 函数式接口:如果一个接口中:有且仅有一个抽象方法的时候,这个接口上面打一个标记@FunctionalInterface
       /* TreeSet<Student> ts = new TreeSet<>(
           (s1,s2) ->{
                //主要条件:学生的年龄从小到大排序
                //s1-----this
                //s2----s
                int num = s1.getAge() - s2.getAge() ;
                //次要条件:年龄相同的,按照学生的姓名:字典顺序比较
                int num2 = (num==0)?(s1.getName().compareTo(s2.getName())):num ;
                return num2;
            }) ;*/

        //创建几个学生对象
        Student s1 = new Student("wangshuai",27) ;
        Student s2 = new Student("wangshuai",27) ;
        Student s3 = new Student("gaoyuanyuan",42) ;
        Student s4 = new Student("gaoyuanyuan",35) ;
        Student s5 = new Student("wenzhang",33) ;
        Student s6 = new Student("mayili",37) ;
        Student s7 = new Student("mayili",35) ;
        Student s8 = new Student("wuqilong",50) ;

        //添加
        ts.add(s1) ;
        ts.add(s2) ;
        ts.add(s3) ;
        ts.add(s4) ;
        ts.add(s5) ;
        ts.add(s6) ;
        ts.add(s7) ;
        ts.add(s8) ;

        System.out.println("姓名\t\t\t年龄");
        //遍历
        for(Student s: ts){
            System.out.println(s.getName()+"\t\t"+s.getAge());
        }
    }
}

21. 接口中定义的方法

public interface Demo {
    //非静态方法
    public  abstract  void show() ;

    //接口中默认的方法
   /* default  void method() { //静态方法
        System.out.println("mehotd Demo....");
    }

    */
    //可以定义静态方法,必须有方法体

    public static void function(){
        System.out.println("function Demo...");
    }
}

22. Map

22.1 具体的子类

   	Map接口---->不能实例化 
    两个子类: hashMap , treeMap.
    Key: 键
    Value: 值
    <K V> : 键值对, 一一对应的,如果键重复,则后来的值(V)会覆盖之前的值
     Java提供另一种方式Map<K,V>:K 键,V 值----存储的一系列的键值对元素
     Map集合特点:不能包含重复的键(必须唯一),如果重复,后面的值会将前面的值覆盖

22.2 基本功能:

    V put(K key,V value)添加键值对元素,返回键对应的值
    void clear() 暴力删除,将Map清空
    V remove(Object key):删除指定的键,返回被删除的键对应的值
    是否包含指定的键:
    boolean containsKey(Object key)
    是否包含指定的值:
    boolean containsValue(Object value)
    int size():获取Map的键值对个数(元素)
    Collection<V> values():获取Map中所有的值
    Set<K> keySet():获取所有的键的集合
    V get(Object key):通过键获取值
    Set<Map.Entry<K,V>> entrySet():获取Map集合中的键值对对象

22.3 Map集合的遍历方式有 两种(键值对):

22.3.1 方式1:“夫妻对”(通用)
    Set<K> keySet():获取所有的键的集合------>找到"丈夫"
    V  get(Object key):通过键获取值---------->通过"丈夫",找对应的"妻子"
22.3.2 方式2: “结婚证”
    Set<Map.Entry<K,V>> entrySet():获取Map集合中的键值对对象 ------>获取到了所有的"结婚证"
    K getKey() 键值对对象获取键---->  结婚证---丈夫
    V getValue() 键值对对对象获取值--->结婚证---找妻子

示例:

public class MapDemo2 {
    public static void main(String[] args) {

        //创建HashMap集合
        Map<String,String> map = new HashMap<>() ;

        //添加键值对元素
        map.put("杨过","小龙女") ;
        map.put("郭靖","黄蓉") ;
        map.put("令狐冲","任莹莹") ;
        map.put("陈玄风","梅超风") ;
        map.put("陈玄风","张佳宁") ;

        // Set<K> keySet():获取所有的键的集合------>找到"丈夫"
        Set<String> set = map.keySet();
        //增强for遍历set集合
        for(String key :set){
            // V  get(Object key):通过键获取值---------->通过"丈夫",找对应的"妻子"
            String value = map.get(key);
            System.out.println(key+"="+value) ;
        }

        System.out.println("-----------------------------------------") ;
        //方式2:
        Set<Map.Entry<String, String>> entrySet = map.entrySet();//获取所有的键值对对象
        for(Map.Entry<String, String> en:entrySet){
          //en:键值对对象
          //K getKey() 键值对对象获取键---->  结婚证---丈夫
          //  V getValue() 键值对对对象获取值--->结婚证---找妻子
            String key = en.getKey() ;
            String value = en.getValue() ;
            System.out.println(key+"="+value) ;
        }
    }
}

22.4 TreeMap

    TreeMap<K,V>:针对元素(键)自然排序或者比较器排序,取决于构造方法
    public TreeMap():自然排序:
    public TreeMap(Comparator<? super K> comparator):比较器排序

例:

    TreeMap<Student,String> 按照学生的年龄从小到大排序
    Student类型:作为键,必须实现Comparable接口,自然排序
public class TreeMapDemo {
    public static void main(String[] args) {

        //public TreeMap():
       // TreeMap<Student,String> tm = new TreeMap<>() ;

        //public TreeMap(Comparator<? super K> comparator):比较器排序
       /* TreeMap<Student,String> tm = new TreeMap<>(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 ;
            }
        }) ;*/
        //lamna 表达式
        TreeMap<Student,String> tm = new TreeMap<>(
           (s1, s2)-> { //compare方法
                //学生的年龄从小到大
                int num = s1.getAge() -s2.getAge() ;
                int num2 = (num==0)?(s1.getName().compareTo(s2.getName())):num ;
                return num2 ;
        }) ;

        //创建几个学生对象
        Student s1 = new Student("gaoyuanyuan",42) ;
        Student s2 = new Student("gaoyuanyuan",42) ;
        Student s3 = new Student("gaoyuanyuan",45) ;
        Student s4 = new Student("zhangjianing",42) ;
        Student s5 = new Student("mayili",30) ;
        Student s6 = new Student("mabaoguo",65) ;
        Student s7 = new Student("wangbaoqiang",35) ;

        //添加到map集合中
        tm.put(s1,"it001") ;
        tm.put(s2,"it002") ;
        tm.put(s3,"it003") ;
        tm.put(s4,"it004") ;
        tm.put(s5,"it005") ;
        tm.put(s6,"it006") ;
        tm.put(s7,"it007") ;

        //遍历
        Set<Student> keySet = tm.keySet();
        for(Student key :keySet){
            String value = tm.get(key);
            System.out.println(key.getName()+"---"+key.getAge());
        }
    }
}

22.5 面试题 : Map和Collection的区别?

1)存储结构不一样
	Collection<E>,单例集合,只能存储一种引用数据类型----->理解为"光棍"
	Map<K,V>,双列集合,可以存储多个引用数据类型---->理解为"夫妻对"
2)遍历方式不同的
	Collection:迭代器遍历---最终使用的增强for
	Map<K,V>: 通用的方式:将所有K获取到,通过键找值!
3)有一定的关系
	Collection里面的Set的子实现类都依赖于Map实现

23. Collections

23.1 Collections:类

	针对集合操作的工具类

23.2 特有功能:

    public static void reverse(List<?> list):将List元素反转
    public static void shuffle(List<?> list):将List集合随机置换
    public static <T extends Comparable<? super T>> void sort(List<T> list):针对List集合自然排序
    public static <T> void sort(List<T> list.Comparator<? super T> c):针对List集合进行比较器排序
    public static <T> int binarySearch(List<? extends Comparable<? super T>> list,T key)
    在集合中查询key元素第一次出现索引值 (集合有序!----List<Integer>)

    获取集合中最大值和最小值元素
    //public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)
    public static <T> List<T> synchronizedList(List<T> list) :和多线程结合使用!
    多线程中讲synchronized

23.3 应用

	使用集合模拟斗地主的洗牌和发牌,发到每个人手上牌有序

分析:

1)创建牌盒
  HashMap<Integer,String>存储的编号和对应的牌
 
  ArrayList<Integer>单独存储编号

  2)
       int index = 0 ;
   装牌:点数,花色
           点数数组: "3","4"....,"10","J","Q","A","2"
         花色---拼接点数
          index ++ ;
 
          单独添加map集合添加(index,"小王") ;
          arrayList集合.add(index) ;
        index ++ ;
          单独添加map集合添加(index,"大王") ;
 
    3)洗牌:洗的是      ArrayList<Integer>存储编号
 
    4)发牌:发的是编号
           三个玩家/底牌 TreeSet<Integer>
 
               发牌的业务算法逻辑
               for(int x = 0 ; x < arrry.size() ; x ++){
              //判断
            //底牌:三张:如果当前x>=array.size()-3
              if(x>=arrry.size()-3){
                  //底牌的:索引值
                  //通过diPai获取在大的集合获取添加
                 diPai.add(arrry.get(x)) ;
                  //三种情况:
 
              }else if(x % 3 == 0 ){
                  //情况1:----玩家1
                  plary1.add(arrry.get(x)) ;
              }else if(x % 3 == 1){
                  //玩家2
                  plary2.add(arrry.get(x)) ;
              }else if(x % 3 == 2){
                  //玩家3
                  plary3.add(arrry.get(x)) ;
              }
              //x % 3==3 :发完了
          }
 
       5)看牌:
              public static void  lookPoker(String name,TreeSet<Integer> ts,HashMap<Integer,String> hm)
public class PokerDemo {
    public static void main(String[] args) {
        //创建牌盒  使用HashMap集合<Integer,String>,Key:它的编号  Value:存储的牌
        HashMap<Integer,String> hm = new HashMap<>() ;
        //创建ArrayList<Integer>,单独存储的牌的编号
        ArrayList<Integer> array = new ArrayList<>() ;

        //装牌
        //定义花色数组
        String[] colors = {"♥","♠","♣","♦"} ;
        //定义点数数组
        String[] numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"} ;

        //定义编号变量index:从0开始
        int index = 0 ;

        //拼接
        for(String number :numbers){
            for(String color:colors){
                String poker = color.concat(number);
                //将编号和进行添加
                hm.put(index,poker) ;
                array.add(index) ;
                //编号++
                index ++;
            }
        }

        //添加小王/和大王
        hm.put(index,"小王") ;
        array.add(index) ;
        index ++ ;
        hm.put(index,"大王") ;
        array.add(index) ;
        //System.out.println(array) ;//编号

        //洗牌:洗的是编号
        Collections.shuffle(array) ;
      //  System.out.println(array);

        //发牌:(发的是编号)发牌需要保证每个玩家手上的牌有序:使用TreeSet集合进行操作
        TreeSet<Integer> player1 = new TreeSet<>() ;
        TreeSet<Integer> player2 = new TreeSet<>() ;
        TreeSet<Integer> player3 = new TreeSet<>() ;
        TreeSet<Integer> diPai = new TreeSet<>() ;
        for(int x = 0 ; x < array.size(); x++){
            //遍历了ArrayList集合中的所有牌对应的编号
            if(x>=array.size()-3){
                //底牌
                diPai.add(array.get(x)) ;
            }else if(x % 3 == 0 ){
                player1.add(array.get(x)) ;
            }else if(x % 3 == 1){
                player2.add(array.get(x)) ;
            }else if(x % 3 == 2){
                player3.add(array.get(x)) ;
            }
        }

        //看牌:三个都可以看牌,看一下底牌的内容:封装成功能
        lookPoker("高圆圆",player1,hm) ;
        lookPoker("赵又廷",player2,hm) ;
        lookPoker("张杨",player3,hm) ;
        lookPoker("底牌",diPai,hm) ;

    }

    public static void lookPoker(String name,TreeSet<Integer> ts,HashMap<Integer,String> hm){
        //输出人的名称
        System.out.print(name+"的牌是:  ") ;
        //TreeSet集合里面存储的自己的牌的编号
        for(Integer key:ts){
            //获取到每一个编号
            //在HashMap集合中通过编号找值
            String poker = hm.get(key);
            System.out.print(poker+"\t") ;
        }
        System.out.println();
    }
}

24. Thread 线程(重点)

24.1 什么是线程

    线程: 执行的最小单元, 线程依赖于进程存在.
    进程: 能够调用系统资源的独立单位(简单理解: 计算机---> 任务管理器: 查看客户端)
    一个进程中包含很多个线程---> 这些线程默认存在"线程组: ThreadGroup",默认的线程组: 就是 main
    举例: 360杀毒软件---> 进程存在
                            杀毒的同时
                            清理其他不用文件
                            瘦身

24.2 单线程和多线程

24.2.1 单线程程序:
	一个程序的执行路径只有一条.
24.2.2 多线程程序:
	一个程序的执行路径,有多条.

24.3 多线程

一个进程包含多个线程, 一个线程---就是"一个任务"
线程的执行具有 " 随机性  ":
	因为现场需要抢占 CPU 的执行权.
现在的计算机: 多进程计算机
	在打游戏的同时,可以听歌,看视频等.
	并非是同时进行,而是CPU不同的时间片.
	CPU的一点点时间片,在不同进程之间高效切换,人类的知觉感觉不到.
	意义:
		大大提高CPU的使用率!	
Jvm:java虚拟机是多线程
至少有两条线程
	一条是main线程,用户线程
	还有一个:垃圾回收线程,需要不断将堆内存中不用的对象进行回收,释放内存空间!

24.4 创建多线程的两种方式:

24.4.1 继承方式
24.4.1.1 步骤
    A)自定义一个类继承Thread类
    B)在自定义的类中重写Thread类的run方法----run方法: 放置的耗时的代码
    (怎么调用的? 是线程启动start,通过jvm调用run方法)

  构造函数:
    public Thread():创建线程

  成员方法:
    public final String getName():获取线程名称
    public final void setName(String name):设置线程名称

    C)在main线程:用户线程中,创建当前这个的类对象---->线程对象
    启动线程:start方法
24.4.1.2 示例:
// 线程类
public class MyThread extends Thread { //public final String getName()

    //重写Thread类的run方法
    //my1,my2线程都要执行run方法...
    @Override
    public void run() {
        //jvm调用的
        //存储耗时代码
        for(int x = 0 ; x <200 ; x ++){
            System.out.println(getName()+":"+x);
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
    //创建线程类对象
        MyThread my1 = new MyThread() ;
        MyThread my2 = new MyThread() ;

        //设置线程名称
        my1.setName("线程1") ;
        my2.setName("线程2") ;
        my1.start();
        my2.start();
       // my1.start();//IllegalThreadStateException:非法线程状态异常
        //一个线程只能调用一次start()方法,调用多次 :线程状态被修改,报错!
    }
}
24.4.2 实现关系
24.4.2.1 步骤
    1)自定义一个类,实现Runnable接口,
    2)重写接口中的run方法:就只有一个run
    3)在main用户线程中,创建当前类的对象,
    然后创建Thread类对象:将当前的那个类的对象作为参数传递
构造方法
    Thread(Runnable target)分配一个新的 Thread对象。
    Thread(Runnable target, String name):创建线程类对象,将资源类对象作为参数传递,并且给线程设置名称
24.4.2.2 示例
//自定义一个类,实现Runnable接口
public class MyRunnable implements Runnable {
    //线程1/线程2:都要操作MyRunnable
    @Override
    public void run() {
        //耗时操作
        for(int x = 0 ; x < 100 ;  x ++){
            //public static Thread currentThread():当前正在运行的线程            System.out.println(Thread.currentThread().getName()+":"+x);
        }
    }
}
public class ThreadDemo {
    public static void main(String[] args) {
        //3)创建MyRunnable类对象
        MyRunnable my = new MyRunnable() ;

        //创建线程Thread类对象
        Thread t1 = new Thread(my,"线程1") ;
        Thread t2 = new Thread(my,"线程2") ;

        //启动线程
        t1.start() ;
        t2.start() ;
    }
}

24.5 面试题(1): 方式2比1的优点

方式1的弊端:
	1) 继承具有局限性,继承了Thread类,run()方法重写了----> jvm调用将Thread的其他功能也继承过来了, 但是线程类中只使用run
	2) 不能体现"数据共享"的概念
	
	多线程: 多个线程"共享一个内存区域"
	举例: 用方式1,3个窗口卖100张票,同一张票可能被卖多次.
方式2的好处:
	1) 实现关系,面向接口编程,体现功能扩展!
	2) 线程对象,在堆内存中的操作的同一个资源类
	体现"多个线程共享一个内存" :MyRunable类的对象.
	3) 使用java的设计模式: 静态代理
	
	java设计模式: 23种;
	创建型: (对象的创建)
	结构型: (类的组成/接口/抽象类)
	行为型

面试题(2) 线程的状态有几种:

线程的生命周期: 从线程的创建-->运行--> 死亡

6种:
     NEW: 新建
     RUNABLE: 运行
     BLOCK: 阻塞		sleep()/wait(), time: 睡眠时间
     WAITING: 死死等待	join(): 等待该线程终止
     TIMED_WAITING: 超时等待  wait(超时时间)
     TERMINATED: 线程终止

24.6 线程中的相关功能

24.6.1 jion()
public final void join() throws InterruptedException:等待该线程终止,才执行其他线程!
	//捕获异常
        try {
            //可能出现问题的代码
            tj2.join() ;
        } catch (InterruptedException e) { //抓取异常:  在内存中创建创建对象 就是当前jvm本身识别的异常类
            e.printStackTrace(); //Throwable类的追踪方法(追踪堆栈)
        }
24.6.2 yield()
	public static void yield():暂停当前正在执行的线程,执行同优先级的其他线程!
24.6.3 setDaemon(boolean on)
    public final void setDaemon(boolean on):标记某个线程是否为守护线程
    参数如果为true,就是守护线程,如果线程都是守护线程,则JVM退出

    注意事项:如果要设置某个线程为守护线程,必须在在启动线程之前,调用setDaemon(true)
24.6.4 Thread线程的优先级
常量字段
    public static final int MIN_PRIORITY  = 1 最小优先级
    public static final int NORM_PRIORITY = 5 默认优先级
    public static final int MAX_PRIORITY = 10 最大优先级

    public final int getPriority():获取优先级
    public final int getPriority():设置优先级
    
   
    优先级越大:抢占CPU的执行权越大/ 优先级越小:抢占到CPU执行权越小
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值