【第四周学习总结】(内容超多,总结的太乱,印象笔记复制过来图没了,学不动了呜呜呜,裂开)

### 1.内部类
如果一个类存在的意义就是为指定的另一个类,可以把这个类放入另一个类的内部。
就是把类定义在类的内部的情况就可以形成内部类的形式。
A类中又定义了B类,B类就是内部类,B类可以当做A类的一个成员看待:


#### 2 特点
1) 内部类可以直接访问外部类中的成员,包括私有成员
2) 外部类要访问内部类的成员,必须要建立内部类的对象
3) 在成员位置的内部类是成员内部类
4) 在局部位置的内部类是局部内部类
#### 3 练习 : 内部类入门案例
```
package cn.tedu.innerclass;
/*本类用作测试内部类的入门案例*/
public class TestInner1 {
    public static void main(String[] args) {
        //3.创建内部类对象,使用内部类的资源
        /*外部类名.内部类名 对象名 = 外部类对象.内部类对象*/
        Outer.Inner oi = new Outer().new Inner();
        oi.delete();
        System.out.println(oi.sum);
        //4.调用外部类的方法--这样是创建了一个外部类的匿名对象,只使用一次
        new Outer().find();
    }
}

//1.创建外部类 Outer
class Outer{
    //1.1创建外部类的成员变量
    String name;
    private int age;
    //1.2创建外部类的成员方法
    public void find(){
        System.out.println("Outer...find()");
        //6.测试外部类如何使用内部类的资源
        //System.out.println(sum);--不能直接使用内部类的属性
        //delete();--不能直接调用内部类的方法
        /*外部类如果想要使用内部类的资源,必须先创建内部类对象
        * 通过内部类对象来调用内部类的资源*/
        Inner in = new Inner();
        System.out.println(in.sum);
        in.delete();
    }
    //2.创建内部类Inner--类的特殊成员
    /*根据内部类位置的不同,分为:成员内部类(类里方法外)、局部内部类(方法里)*/
    class Inner{
        //2.1定义内部类的成员变量
        int sum = 10;
        //2.2定义内部类的成员方法
        public void delete(){
            System.out.println("Inner...delete()");
            //5.测试内部类是否可以使用外部类的资源
            /*结论:内部类可以直接使用外部类的资源,私有成员也可以!*/
            System.out.println(name);
            System.out.println(age);
            /*注意:此处测试完毕需要注释掉,否则来回调用
            * 会抛出异常StackOverFlowException栈溢出异常*/
            //find();
        }
    }
}```

* * *#### 4 成员内部类
4.1 练习 : 被private修饰
```
`package cn.tedu.innerclass;
/**本类用来测试成员内部类被private修饰*/
public class TestInner2 {
    public static void main(String[] args) {
        /**怎么使用内部类Inner2的资源?*/
        //4.创建内部类Inner2对象进行访问
        //Outer2.Inner2 oi = new Outer2().new Inner2();
        //oi.eat();
        
        /**如果Inner2被private修饰,无法直接创建对象该怎么办?*/
        //7.创建外部类对象,间接访问私有内部类资源
        new Outer2().getInner2Eat();
    }
}
//1.创建外部类Outer2
class Outer2{
    //6.提供外部类公共的方法,在方法内部创建Inner2内部类对象,调用内部类方法
    public void getInner2Eat() {
        Inner2 in = new Inner2();//外部类可以访问内部类的私有成员
        in.eat();
    }
    //2.1创建成员内部类Inner2
    /**成员内部类的位置:类里方法外*/
    //5.成员内部类,被private修饰私有化,无法被外界访问
    private class Inner2{
        //3.创建内部类的普通成员方法
        public void eat() {
            System.out.println("我是Inner2的eat()");
        }
    }
}`
```


总结:
成员内部类被Private修饰以后,无法被外界直接创建创建对象使用
所以可以创建外部类对象,通过外部类对象间接访问内部类的资源
4.2 练习 : 被static修饰
```

package cn.tedu.innerclass;
/**本类用来测试成员内部类被static修饰*/
public class TestInner3 {
    public static void main(String[] args) {
        /**如何访问内部类的show()?*/
        //4.创建内部类对象访问show()
        //方式一:按照之前的方式,创建内部类对象调用show()
        //Outer3.Inner3 oi = new Outer3().new Inner3();
        //oi.show();
        //方式二:创建匿名内部类对象访问show()
        //new Outer3().new Inner3().show();
        
        /**现象:当内部类被static修饰以后,new Outer3()报错*/
        //6.用static修饰内部类以后,上面的创建语句报错,注释掉
        //通过外部类的类名创建内部类对象
        Outer3.Inner3 oi = new Outer3.Inner3();
        oi.show();
        
        //7.匿名的内部类对象调用show()
        new Outer3.Inner3().show();
        
        //9.访问静态内部类中的静态资源--链式加载
        Outer3.Inner3.show2();
    }
}

//1.创建外部类Outer3
class Outer3{
    //2.创建成员内部类Inner3
    //5.内部类被static修饰—并不常用!浪费内存!
    static class Inner3{
        //3.定义成员内部类中普通的成员方法
        public void show() {
            System.out.println("我是Inner3类的show()");
        }
        //8.定义成员内部类的静态成员方法
        static public void show2() {
            System.out.println("我是Inner3的show2()");
        }
    }
}
```


**总结:
静态资源访问时不需要创建对象,可以通过类名直接访问
访问静态类中的静态资源可以通过”. . . ”链式加载的方式访问**

* * *

#### 5 局部内部类
```

package cn.tedu.innerclass;
/**本类用来测试局部内部类*/
public class TestInner4 {
    public static void main(String[] args) {
        /**如何使用内部类的资源呢?
         * 注意:直接调用外部类的show()是无法触发内部类功能的
         * 需要再外部类中创建内部类对象并且进行调用,才能触发内部类的功能
         * */
        //5.创建外部类对象调用show()
        //7.当在外部类show()中创建局部内部类对象并且进行功能调用后,内部类的功能才能被调用
        new Outer4().show();
    }
}
//1.创建外部类Outer4
class Outer4{
    //2.创建外部类的成员方法
    public void show() {
        //3.创建局部内部类Inner4—不太常用!!!
        /**位置:局部内部类的位置在方法里*/
        class Inner4{
            //4.创建局部内部类的普通属性与方法
            String name;
            int age;
            public void eat() {
                System.out.println("我是Inner4的eat()");
            }
        }
        /**如何使用局部内部类的资源?*/
        //6.在show()里创建内部类对象
        Inner4 in = new Inner4();
        in.eat();
        System.out.println(in.name);
        System.out.println(in.age);
    }
}

```

* * *

#### 6 匿名内部类

```
package cn.tedu.innerclass;
/*本类用于测试匿名内部类
* 匿名内部类没有名字,通常与匿名对象结合在一起使用*/
public class TestInner5 {
    public static void main(String[] args) {
        //传统方式:创建接口的实现类+实现类实现接口中的抽象方法+创建实现类对象+通过对象调用方法
        //3.创建接口一对应的匿名对象与匿名内部类,并调用实现了的方法save()
        new Inter1(){
            @Override
            public void save() {
                System.out.println("save()...");
            }
            @Override
            public void get() { }
        }.save();

        //5.创建抽象类对应的匿名对象与匿名内部类
        new Inter2(){
            @Override
            public void drink() {
                System.out.println("一人饮酒醉");
            }
        }.drink();
        //7.调用普通类的功能怎么调用?创建匿名对象直接调用
        new Inter3().powerUp();
        new Inter3().powerUp();//new了2次,所以是两个匿名对象
        /*如果想要多次使用实现后的功能,还是要创建普通的对象
        * 匿名对象只能使用一次,一次只能调用一个功能
        * 匿名内部类其实就充当了实现类的角色,去实现未实现的抽象方法,只是没有名字而已*/
        Inter3 in = new Inter3();
        in.study();
        in.study();
        in.study();
        in.study();
        in.study();
        in.study();

    }
}

//1.创建接口
interface Inter1{
    //2.定义接口中的抽象方法
    void save();
    void get();
}
//4.创建抽象类
abstract class Inter2{
    public void play(){
        System.out.println("Inter2...play()");
    }
    abstract public void drink();
}
//6.创建普通类
class Inter3{
    public void study(){
        System.out.println("什么都阻挡不了我想学习赚钱的决心");
    }
    public void powerUp(){
        System.out.println("我们会越来越强的!");
    }
}
```


总结:
匿名内部类属于局部内部类,而且是没有名字的局部内部类,通常和匿名对象一起使用


* * *

## 2.Java的常用类
```
`Object:重点类 所有的类的父类:几乎的成员方法都需要被任何子类重写
toString()
本方法用于返回对应对象的字符串表示

hashCode()
本方法用于返回对应对象的哈希码值
小贴士:哈希码值的得出是通过一种算法,意在让不同的对象具有不同的哈希码值,用于区分不同的对象.
但是有时候也存在不同对象哈希码值相同的特殊情况,我们称之为”哈希碰撞”现象

equals()
本方法用于指示其他某个对象是否与当前对象”相等”
String类:重点类(开发中使用最多的)String s = new String("hello") ;
String s2 = "hello" ; //常量---常量池中 (推荐这种方式)
转换功能:
char[] toCharArray()
byte[] getBytes()
截取
    subString(int begin,int end) 包前不包后
字符串的其他功能:替换/去除两端空格...
    StringBuffer:字符串缓冲区
    append(传递任何数据类型) :追加
    StringBuffer----String类型
    String类型----StringBuffer
Integer :int类型包装类类型:
String--> Integer-->int
    Integer.parseInt(String字符串值)--->int
String---->Long--> long
    Long.parseLong(String字符串)---long
int-->Integer-->String
    Character:char类型的包装类类型:
判断功能:
public static boolean isUpperCase() :是否为大写
public static boolean isLowerCase() :是否为小写
public static boolean isrDigit() :数字字符
java.util.Date:日期类 :重点类型转换
String:文本格式 ------Date格式
应用场景:
网页中日期组件
2022-8-16:String 文本格式------>Date格式
Calendar:日历类/Math:数学运算/Random:随机数生成器
Object类的成员方法和String类重点构造方法总结Object类里面的toString():建议所有子类重写,直接输出对象名称,看到的一个简明扼
要的信息表达式而不是一堆地址值;
**Object里面的equals() :建议所有子类重写, 否则,默认比较的引用数据类型的地址值**
是否一样,重写之后,比较的是成员信息是否相同;
String类
构造方法
String(char[] chs) :将字符数组构造成String
String(byte[] bytes):将字节数组构造成String
String类的特点:
一旦被创建,其值不能被更改;
面试题
* String s1 = "hello" ;
*
String s2 = new String("hello") ;
*
他们分别创建了几个对象,有什么区别呢?
*
s1: 现在常量池中,是否存在这个常量,如果存在,直接返回地址值;否
则,开辟新的空间地址值,赋值s1
*
s2:在堆内存中申请空间,然后常量"hello",
*
还需要在常量池中找是否存在这个常量,有,就返回地址,重新开辟常
量池空间
*
*
*
共同点:都表示创建"hello"字符串实例`
```
### String类
```
1.String是一个封装char[]数组的对象,字符串不可变
通过下图中的底层实现可以看出:被final修饰,是常量
String str = “abc”; 等效于:char data[] = {‘a’, ‘b’, ‘c’};
```
![ab6894e7a3c77bd8513c8a3dd36fa5eb.png](en-resource://database/616:0)


```
2. 创建String对象的方式
方式一:
String(char[] value) 分配一个新的 String,使其表示字符数组参数中当前包含的字符序列。
方式二: String str = “abc”;
```
![071a720a61b91a4c4bf7351c164bb32a.png](en-resource://database/618:1)


```
如果是第一次使用字符串,java会在字符串堆中常量池创建一个对象。
再次使用相同的内容时,会直接访问堆中常量池中存在的对象。
```
```
3 常见方法
String API总结
int hashCode() 返回此字符串的哈希码。
boolean equals(Object anObject) 将此字符串与指定的对象比较,比较的是重写后的串的具体内容
String toString() 返回此对象本身(它已经是一个字符串!)。

int length() 返回此字符串的长度。
String toUpperCase() 所有字符都转换为大写。
String toLowerCase() 所有字符都转换为小写
boolean startsWith(String prefix) 测试此字符串是否以指定的元素开头。
boolean endsWith(String suffix) 测试此字符串是否以指定的字符串结束。

char charAt(int index) 返回指定索引/下标处的 char 值/字符
int indexOf(String str) 返回指定字符在此字符串中第一次出现处的索引。
int lastIndexOf(String str) 返回指定字符在此字符串中最后一次出现处的索引。
String concat(String str) 将指定字符串连接/拼接到此字符串的结尾,注意:不会改变原串
String[] split(String regex) 根据给定元素来分隔此字符串。

String trim() 返回去除首尾空格的字符串
byte[] getBytes() 把字符串存储到一个新的 byte 数组中
String substring(int beginIndex) 返回一个新子串,从指定下标处开始,包含指定下标
String substring(int beginIndex, int endIndex) 返回一个新子串,从执定下标开始,到结束下标为止,但不包含结束下标
static String valueOf(int i) 把int转成String
```
![6135bf5f84a26adffc0cf7e877624623.png](en-resource://database/628:0)
![d7adaed3e02c66f8ada243a1802b1fe8.png](en-resource://database/630:0)

##### 练习
```
package cn.tedu.api;
/*本类用于练习String类的使用*/
public class TestString {
    public static void main(String[] args) {
        //1.创建String的方式一
        /*1.字符串类型底层维护的是char[],存在堆中*/
        char[] value = {'a','b','c'};
        String s1 = new String(value);//触发String(char[])的含参构造来创建对象
        String s11 = new String(value);//触发String(char[])的含参构造来创建对象
        //2.创建String的方式二
        String s2 = "abc";
        String s22 = "abc";
        String s3 = "ccc";
        //3.测试
        System.out.println(s1 == s2);//false,一个在堆里,一个在堆中常量池
        System.out.println(s1 == s11);//false,两个不同的对象,地址值不同
        System.out.println(s2 == s22);//true,都在堆中常量池,并且指向同一个,所以地址值相同
        System.out.println(s2 == s3);//false,都在堆中常量池,但是数据不同,指向两个地址

        /*Object类中equals()的默认实现是通过==来比较的。
        但是String类已经重写过了继承自Object中的equals()
        重写后,不再按照==比较,而是比较两个字符串的具体内容
        也就是说,不论创建方式,只要是串的内容一致,equals()就返回true
        * */
        System.out.println(s1.equals(s2));//true
        System.out.println(s1.equals(s11));//true

        System.out.println(s2.equals(s3));//false
    }
}
```

![c01ee2924443e303a12f0878d6421107.png](en-resource://database/620:0)
![500cb3094f12c209bf249edca54823e8.png](en-resource://database/622:0)

![d1b02e7a299ce6317459afc11d21923d.png](en-resource://database/634:0)

#### 5 StringBuilder/StringBuffer
```
1 特点
封装了char[]数组
是可变的字符序列
提供了一组可以对字符内容修改的方法
常用append()来代替字符串做字符串连接”+”
内部字符数组默认初始容量是16:super(str.length() + 16);
如果大于16会尝试将扩容,新数组大小原来的变成2倍+2,容量如果还不够,直接扩充到需要的容量大小。int newCapacity = value.length * 2 + 2;
StringBuffer 1.0出道线程安全,StringBuilder1.5出道线程不安全
2 常见方法
append()
package cn.tedu.api;
/*本类用于测试字符串的拼接*/
public class TestString3 {
    public static void main(String[] args) {
        //需求:将26个字母拼接10000次
        String s = "abcdefghijklmnopqrstuvwxyz";
        //method1(s);//使用方式一拼接字符串
        method2(s);//使用方式二拼接字符串
    }
    //使用方式二拼接字符串
    private static void method2(String s) {
        //1.创建工具类对象
        StringBuffer sb = new StringBuffer();
        StringBuilder sb2 = new StringBuilder();
        //5.添加一个计时的功能
        //5.1拼接之前获取系统当前时间作为开始时间
        long t1 = System.currentTimeMillis();
        //2.拼接10000次
        for (int i = 0; i < 10000; i++) {
            //3.使用工具类对象的append()进行拼接
            //sb.append(s);
            sb2.append(s);
        }
        //5.2拼接之后获取系统当前时间作为结束时间
        long t2 = System.currentTimeMillis();
        //4.打印拼接的效果
        //System.out.println(sb);
        System.out.println(sb2);
        //5.3打印拼接总共消耗的时间
        System.out.println(t2-t1);
    }

    //使用方式一完成字符串的拼接
    private static void method1(String s) {
        //1.创建一个变量用来保存拼接后的效果
        String result = "";
        //5.给程序添加一个计时的功能
        //5.1获取循环开始的系统当前时间
        long t1 = System.currentTimeMillis();
        //2.创建循环执行10000次
        for (int i = 0; i < 10000; i++) {
            //3.进行字符串的拼接
            result = result + s;
        }
        //5.2获取循环拼接之后的系统当前时间
        long t2 = System.currentTimeMillis();
        //4.打印拼接后的效果
        System.out.println(result);
        //5.打印花费的时间
        System.out.println(t2-t1);
        System.out.println(t2);
    }

}
```
#### 实际开发中:需要把A类型--B
#### 类型,然后B类型转换成A类型?
```
A类型--->B类型,目的是为了使用B类型的特有功能,但是结果类型可能A类型,
所有B类型的功能使用完之后,然后在转换A类型;
只要牵扯类型转换,必须记住常用的转换
/**
* 类型转换
* StringBuffer和String的类型转换
*
* String---->StringBuffer,目的为了StringBuffer的特有功能
* StringBuffer--->String,结果需要是String类型
*/
public class StringBufferDemo3 {
public static void main(String[] args) {
//String----StringBuffer
//有一个字符串
String s = "hello" ;
//StringBuffer sb = s;
//方式1:利用StringBuffer()无参构造方法+append(String str)
//创建一个字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
sb.append(s) ;
System.out.println(sb); //字符串缓冲区存储的数据内容 "hello",类型是
StringBuffer
System.out.println("----------------------------------");
//方式2:利用StringBuffered的有参构造方法StringBuffer(String str)
StringBuffer sb2 = new StringBuffer(s) ;
System.out.println(sb2);
System.out.println("-----------------------StringBuffer转换成String--
---------------------");
//StringBuffer --->String
StringBuffer buffer = new StringBuffer("helloworld") ;//字符序列是
helloworld,外面的类型StringBuffer
//方式1:public String(StringBuffer buffer) ;String类的构造方法
String str = new String(buffer) ;
System.out.println(str) ; //内容"helloworld",类型String
System.out.println("-------------------------------------");
//方式2:public String toString() 显示的应该是字符串缓冲区中的实际的
字符序列内容
String str2 = buffer.toString();
System.out.println(str2);
/*int i = 100 ;
 String s4 = "100" ;*/
}
}

```
##### ==和equals的区别
```
1.当使用= =比较时,如果相比较的两个变量是引用类型,那么比较的是两者的物理地值(内存地址),如果相比较的两个变量都是数值类型,那么比较的是具体数值是否相等。
2.当使用equals()方法进行比较时,比较的结果实际上取决于equals()方法的具体实现
众所周知,任何类都继承自Object类,因此所有的类均具有Object类的特性,比如String、integer等,他们在自己的类中重写了equals()方法,此时他们进行的是数值的比较,而在Object类的默认实现中,equals()方法的底层是通过==来实现的。
```
#####  StringBuilder和StringBuffer的区别
```
1.在线程安全上 :
–StringBuffer是旧版本就提供的,线程安全的。@since JDK1.0
–StringBuilder是jdk1.5后产生,线程不安全的。@since 1.5
2. 在执行效率上,StringBuilder > StringBuffer > String
3.源码体现:本质上都是在调用父类抽象类AbstractStringBuilder来干活,只不过Buffer把代码加了同步关键字,使得程序可以保证线程安全问题。

```
![e28f722758372c68517c85fcfbda76fa.png](en-resource://database/640:0)
![86b59d1b46f02a81138d8e9c783d929f.png](en-resource://database/642:0)
#### Integer内部缓存区
```
/**
* @author 高圆圆
* @date 2022/8/17 17:13
* 将一个常量值赋值给Integer类型,通过反编译工具 调用的Integer.valueOf(int类
型的值)
*/
public class IntegerTest {
public static void main(String[] args) {
Integer i1 = 127 ;
Integer i2 = 127 ;
System.out.println(i1==i2) ;//true
System.out.println(i1.equals(i2)) ;//true
 Integer i3 = 127 ;
Integer i4 = new Integer(127) ;
System.out.println(i3==i4) ; //false
System.out.println(i3.equals(i4)) ;//true
//值128 超过-128-127
Integer i5 = 128 ; //Integer i5 = new Integer(128);
Integer i6 = 128 ; //Integer i6 = new Integer(128);
System.out.println(i5==i6) ; //false
System.out.println(i5.equals(i6)) ;//true
Integer i7 = new Integer(128) ;
Integer i8 = new Integer(128) ;
System.out.println(i7==i8) ;//false
System.out.println(i7.equals(i8)) ;//true
}
}
/**
* Integer的valueOf(int i)的原码
* p
* class Integer{
* static final Integer cache[]; //Integer类型数组
* ublic static Integer valueOf(int i) { //127
* * if (i >= IntegerCache.low && i <= IntegerCache.high)
* //范围-128-127之间:传递int类型的值在-128-127之间,直接从内部缓存区:(数组
里面取数据即可!)
* * return IntegerCache.cache[i + (-IntegerCache.low)];
* 如果超过这个范围,new Integer(int类型的值)
* * return new Integer(i);
* * }
* //Integer的静态的成员内部类
* private static class IntegerCache { //Integer的内部缓存区
* static final int low = -128;
* static final int high;
* int h = 127 ;
* high = h;
    * }
* }
```
### Integer内部缓存区
```
/**
* @author 高圆圆
* @date 2022/8/17 17:13
* 将一个常量值赋值给Integer类型,通过反编译工具 调用的Integer.valueOf(int类
型的值)
*/
public class IntegerTest {
public static void main(String[] args) {
Integer i1 = 127 ;
Integer i2 = 127 ;
System.out.println(i1==i2) ;//true
System.out.println(i1.equals(i2)) ;//true
 Integer i3 = 127 ;
Integer i4 = new Integer(127) ;
System.out.println(i3==i4) ; //false
System.out.println(i3.equals(i4)) ;//true
//值128 超过-128-127
Integer i5 = 128 ; //Integer i5 = new Integer(128);
Integer i6 = 128 ; //Integer i6 = new Integer(128);
System.out.println(i5==i6) ; //false
System.out.println(i5.equals(i6)) ;//true
Integer i7 = new Integer(128) ;
Integer i8 = new Integer(128) ;
System.out.println(i7==i8) ;//false
System.out.println(i7.equals(i8)) ;//true
}
}
/**
* Integer的valueOf(int i)的原码
* p
*
* class Integer{
*
* static final Integer cache[]; //Integer类型数组
*
* ublic static Integer valueOf(int i) { //127
* * if (i >= IntegerCache.low && i <= IntegerCache.high)
* //范围-128-127之间:传递int类型的值在-128-127之间,直接从内部缓存区:(数组
里面取数据即可!)
* * return IntegerCache.cache[i + (-IntegerCache.low)];
*
* 如果超过这个范围,new Integer(int类型的值)
* * return new Integer(i);
* * }
* //Integer的静态的成员内部类
* private static class IntegerCache { //Integer的内部缓存区
* static final int low = -128;
* static final int high;
* int h = 127 ;
* high = h;
* }
* }
```
### int和String的相互转换
```
/**
* @author 高圆圆
* @date 2022/8/17 17:02
*
*
* 基本数据类型:八种 如何转换String
* String---->基本类型
* 使用 int举例
*
* int---->String :Integer.valueOf(int类型的值)
* String---->int :Integer.parseInt(数字字符串)
*/
public class IntegerDemo3 {
public static void main(String[] args) {
//int---->String
int i = 10 ;
//方式1:字符串拼接 符号+
System.out.println(i+"");//"10"
//方式2:int---->Integer:装箱---->String
//Intege(int i)
Integer ii = new Integer(i) ;
//Integer---->String :public String toString()
String s = ii.toString();
System.out.println(s) ; //"10"
//方式3:Integer类的静态方法:public static String toString(int i) (推
荐)
 String s2 = Integer.toString(i);
System.out.println(s2);
System.out.println("-----------------------------------------------")
;
//String --->int
String str = "100" ;// 数字字符串
//方式1:推荐 Integer 静态方法 public static int parseInt(String
str): "最常用的"
int number = Integer.parseInt(str);
System.out.println(number); //100
//方式2:String---->Integer--->int
//Integer(String s)
Integer integ = new Integer(str) ;
//public int intValue()
int number2 = integ.intValue();
System.out.println(number2) ;
}
}
```

## 1 Collection接口
### 1.1 集合前言
```
Java语言的java.util包中提供了一些集合类,这些集合类又称之为容器
提到容器不难想到数组,集合类与数组最主要的不同之处是,数组的长度是固定的,集合的长度是可变的,而数组的访问方式比较单一,插入/删除等操作比较繁琐,而集合的访问方式比较灵活
```
![341b55a03385a2819c5e991071093f55.png](en-resource://database/644:0)

```
常用的集合类有List集合,Set集合,Map集合,其中List集合与Set集合继承了Collection接口,各个接口还提供了不同的实现类.
```
![6d778f450509309d793cd5da0ac492d8.png](en-resource://database/646:0)
#### 1.2 集合概念
```
集合的英文名称是Collection,是用来存放对象的数据结构,而且长度可变,可以存放不同类型的对象,并且还提供了一组操作成批对象的方法.Collection接口层次结构 中的根接口,接口不能直接使用,但是该接口提供了添加元素/删除元素/管理元素的父接口公共方法.
由于List接口与Set接口都继承了Collection接口,因此这些方法对于List集合和Set集合是通用的.

```
#### 1.3 集合的继承结构

```
Collection接口
List 接口【数据有下标,有序,可重复】
ArrayList子类
LinkedList子类
Set 接口【数据无下标,无序,不可重复】
HashSet子类
Map 接口【键值对的方式存数据】
HashMap子类
```
![1afb864fe7a72ab69b5138b294f6d970.png](en-resource://database/648:0)
package cn.tedu.collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
#### 1.5练习
/**本类用于测试Collection接口*/
```
public class TestCollection {
    public static void main(String[] args) {
        //1.创建Collection相关的对象
        //Collection c = new Collection();//报错,因为Collection是接口
        //<Integer>是泛型,用来约束集合中的数据类型,不能是基本类型,必须是引用类型
        Collection<Integer> c = new ArrayList<>();

        //2.1测试集合中的常用方法--单个集合间的操作
        c.add(100);//向集合中添加元素 Ctrl+D快速向下复制
        c.add(200);//向集合中添加元素
        c.add(300);//向集合中添加元素
        c.add(400);//向集合中添加元素
        c.add(500);//向集合中添加元素
        System.out.println(c);//直接打印集合,查看集合中的元素

//        c.clear();//清空当前集合中的所有元素
//        System.out.println(c);

        System.out.println(c.hashCode());//获取集合对象的哈希码值
        System.out.println(c.toString());//打印集合的具体元素
        System.out.println(c.equals(200));//false,集合对象c与值200是否相等

        System.out.println(c.contains(200));//true,c集合中是否包含指定元素200
        System.out.println(c.isEmpty());//false,判断集合是否为空
        System.out.println(c.remove(100));//true,移除集合中的指定元素,成功返回true
        System.out.println(c);//[200, 300, 400, 500]
        System.out.println(c.size());//4,返回集合的元素个数

        Object[] array = c.toArray();//将指定的集合转为数组Object[]
        System.out.println(Arrays.toString(array));//[200, 300, 400, 500]

        //2.2测试多个集合间的操作
        Collection<Integer>  c2 = new ArrayList<>();//创建第2个集合
        c2.add(2);//向c2集合添加元素
        c2.add(4);//向c2集合添加元素
        c2.add(5);//向c2集合添加元素
        System.out.println(c2);//查看c2集合中的元素

        c.addAll(c2);//把c2集合的所有元素添加到c集合当中
        System.out.println(c);//c2集合的所有元素追加到了c集合末尾
        System.out.println(c2);//c2集合本身没有任何改变

        //当前集合c是否包含指定集合c2中的所有元素
        System.out.println(c.containsAll(c2));
        System.out.println(c.contains(200));//c是否包含单个指定元素200

        System.out.println(c.removeAll(c2));//删除c集合中属于c2集合的所有元素
        System.out.println(c);

        System.out.println(c.add(5));
        System.out.println(c);
        System.out.println(c.retainAll(c2));//取c集合与c2集合的交集(公共元素)
        System.out.println(c);//[5]

        //3.迭代集合/遍历集合
        /**迭代步骤:
         * 1.获取集合的迭代器 c.iterator();
         * 2.判断集合中是否有下一个可迭代的元素 it.hasNext()
         * 3.获取当前迭代到的元素 it.next()*/
        Iterator<Integer> it = c.iterator();
        while(it.hasNext()){
            Integer num = it.next();
            System.out.println(num);
        }
    }
}
```
## 2 泛型
#### 2.1 概念
我们可以观察一下,下面的代码中有什么元素是我们之前没见过的呢?
![ebdbfe438468619f096472087d510f47.png](en-resource://database/650:0)

```
其实就是< ? >的部分,它就是泛型
泛型是(Generics)JDK1.5 的一个新特性,通常用来和集合对象一起使用
泛型概念非常重要,它是程序的增强器,它是目前主流的开发方式
```

#### 2.2 作用
```
那泛型有什么作用呢?
我们可以把泛型理解成一个“语法糖”,本质上就是编译器为了提供更好的可读性而提供的一种小手段,小技巧,虚拟机层面是不存在所谓“泛型”的概念的。是不有点神奇,不知所云,别着急等我讲完你就清楚了。

我们可以通过泛型的语法定义<>,来约束集合中元素的类型,编译器可以在编译期根据泛型约束提供一定的类型安全检查,这样可以避免程序运行时才暴露BUG,代码的通用性也会更强
泛型可以提升程序代码的可读性,但是它只是一个“语法糖”(编译后这样的部分会被删除,不出现在最终的源码中),所以不会影响JVM后续运行时的性能.
```

#### 2.3 泛型示例
```
示例1 : 我们创建一个ArrayList,看到eclipse发出黄线警告,这是为什么呢?
原因:ArrayList定义时使用了泛型,在声明时需要指定具体的类型 

```
![ba645e59d678afe7d8cd877d90d39d6a.png](en-resource://database/652:1)
![945ba47950ca16f52c0d5fdd036dbb1f.png](en-resource://database/654:0)
![401221cceeab4b7f68aaec21c37f02f2.png](en-resource://database/656:0)


```

我们把这个”<>”的方式称之为泛型,那么泛型有什么样的作用呢?就是在编译阶段检查传入的参数是否正确
有了泛型,我们可以看到要求存放的是String类型,而测试时存放的是int类型的100,所以编译器报错:
类型List的add方法要求添加的类型为String类型,int类型不匹配,不能正确存入
```

#### 2.4 泛型声明
![f15360d60b476b86c6f316b6edd3d107.png](en-resource://database/658:0)

```
泛型可以在接口 类 方法上使用

在方法的返回值前声明了一个,表示后面出现的E是泛型,而不是普通的java变量
```
package cn.tedu.generic;

import java.util.ArrayList;
import java.util.List;

```
/**本类用于测试泛型的优点*/
public class TestGeneric1 {
    public static void main(String[] args) {
        /**1.泛型是怎么来的?--想要模拟数组的数据类型检查*/
        String[] a = new String[5];//创建一个用来存放String类型数据的数组,长度为5
        a[2] = "泡泡";
        a[4] = "涛涛";
        //数组的好处:在编译时期检查数据的类型,如果不是要求的类型会在编译器就报错
        //a[0] = 1;
        //a[1] = 8.8;
        //a[3] = 'c';
        
        /**2.泛型通常会结合着集合一起使用*/
        List list = new ArrayList();//注意导包:java.util...
        //没有泛型,数据类型根本没有约束 -- 太自由!!!
        list.add("江江");
        list.add(1);
        list.add(8.8);
        list.add('a');
        System.out.println(list);//通过打印查看集合中的元素
        
        /**3.引入泛型--主要目的是想通过泛型来约束集合中元素的类型<?>*/
        /**4.泛型的好处:可以把报错的时机提前,在编译期就报错,而不是运行后抛出异常
         * 在向集合中添加元素时,会先检查元素的数据类型,不是要求的类型就编译失败
         * */
        List<String> list2 = new ArrayList<String>();//注意导包:java.util...
        list2.add("雷神");//约束了类型以后,只可以传String参数
        //list2.add(1);
        //list2.add(8.8);
        //list2.add('d');
        
        /**5.<type>--type的值应该如何写?
         * 需要查看要存放的数据类型是什么,根据类型进行定义
         * 但是type必须是引用类型,不是基本类型
         */
        //List<int> list3 = new ArrayList<int>();//注意导包:java.util...
        List<Integer> list3 = new ArrayList<Integer>();//注意导包:java.util...
        list3.add(100);
        list3.add(200);
        System.out.println(list3);
    }
}

```
```
package cn.tedu.generic;
/**本类用来测试泛型的优点2*/
public class TestGeneric2 {
    public static void main(String[] args) {
        //需求:打印指定数组中的所有元素
        Integer[] a = {1,2,3,4,5,6,7,8,9,10};
        print(a);
        
        String[] b = {"大哥","二哥","三哥","四哥","五哥","六哥","小弟"};
        print(b);
        
        Double[] c = {6.0,6.6,6.66,6.666,6.6666};
        print(c);
    }
    /**1.泛型可以实现通用代码的编写,使用E表示元素的类型是Element类型 -- 可以理解成神似多态*/
    /**2.泛型的语法要求:如果在方法上使用泛型,必须两处同时出现,一个是传入参数的类型,一个是返回值前的泛型类型,表示这是一个泛型*/
    private static <E> void print(E[] e) {
        for(E d :e) {
            System.out.println(d);
        }
    }

//    public static void print(Double[] c) {
//        for(Double d : c) {
//            System.out.println(d);
//        }
//    }
//
//    public static void print(String[] b) {
//        for(String s : b) {
//            System.out.println(s);
//        }
//    }
//
//    public static void print(Integer[] a) {
//        //使用普通循环遍历数组比较复杂,引入高效for循环
//        //普通循环的好处是可以控制循环的步长(怎么变化)
//        for (int i = 0; i < a.length; i=i+2) {
//            System.out.println(a[i]);
//        }
//        /**
//         * 高效for/foreach循环--如果只是单纯的从头到尾的遍历,使用增强for循环
//         * 好处:比普通的for循环写法简便,而且效率高
//         * 坏处:没有办法按照下标来操作值,只能从头到尾依次遍历
//         * 语法:for(1 2 : 3){代码块} 3是要遍历的数据  1是遍历后得到的数据的类型 2是遍历起的数据名
//         */
//        for(Integer i : a) {
//            System.out.print(i);
//        }
//    }
}

```
### 3 List接口
#### 3.1 概述
有序的colletion(也称为序列).此接口的用户可以对列表中的每个元素的插入位置进行精确的控制,用户可以根据元素的整数索引(在列表中的位置)来访问元素,并搜索列表中的元素.

#### 3.2 特点
元素都有下标
数据是有序的
允许存放重复的元素
#### 3.3 List方法速查表
![b0f9f87a96ed7af3b359c3a9165ea8d2.png](en-resource://database/660:0)
```
package cn.tedu.collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**本类用于测试List接口*/
public class TestList {
    public static void main(String[] args) {
       //1.创建List的多态对象,注意List是接口,不可实例化
       List<String> list = new ArrayList<String>();

       //2.测试继承自Collection中的方法
       list.add("大力娃");//向list集合中存入数据
       list.add("千顺娃");
       list.add("头铁娃");
       list.add("喷火娃");
       list.add("喷水娃");
       list.add("隐身娃");
       list.add("小紫娃");
       System.out.println(list);//查看集合中的元素

//       list.clear();//清空集合
//       System.out.println(list);
       System.out.println(list.contains("喷火娃"));//true,判断集合是否包含指定元素
       System.out.println(list.equals("喷水娃"));//false,集合对象与String数据不等
       System.out.println(list.isEmpty());//false,判断集合是否为空
       System.out.println(list.remove("小紫娃"));//移除集合中指定的元素
       System.out.println(list.size());//6,获取集合中元素的个数
       System.out.println(Arrays.toString(list.toArray()));//将集合转成数组

       //3.测试List接口自己的方法--List有序,可以根据索引来操作集合中的元素
       list.add("小蝴蝶");//追加在最后
       list.add(1,"蛇精");//在指定的索引处添加元素
       list.add(3,"小蝴蝶");//在指定的索引处添加元素
       System.out.println(list);

       System.out.println(list.indexOf("小蝴蝶"));//3,获取指定元素第一次出现的索引
       System.out.println(list.lastIndexOf("小蝴蝶"));//8,获取指定元素最后一次出现的索引

       System.out.println(list);
       //根据索引删除元素,并将被删除的元素返回
       System.out.println(list.remove(5));
       System.out.println(list);
       System.out.println(list.get(3));//获取指定索引处的元素
       System.out.println(list.set(7,"蝎子精"));//修改指定索引处元素的值为蝎子精
       System.out.println(list);

       //4.测试集合间的操作
       List<String> list2 = new ArrayList<>();//创建第2个集合
       list2.add("1");//向集合2中添加元素
       list2.add("2");
       list2.add("3");
       list2.add("4");
       System.out.println(list2);//查看集合中的元素
       //将2集合的所有元素添加到list集合中
       System.out.println(list.addAll(list2));
       //将2集合的所有元素添加到list集合的指定位置
       System.out.println(list.addAll(1,list2));
       System.out.println(list);
       //判断list集合中是否包含list2集合中的所有元素
       System.out.println(list.containsAll(list2));
       //移除list集合中属于list2集合中的所有元素
       System.out.println(list.removeAll(list2));
       System.out.println(list);
    }
}
```

### 4 ArrayList
#### 4.1 概述
*存在java.util
*包中内部是用数组结构存放数据,封装数组的操作,每个对象都有下标
*内部数组默认的初始容量是10,如果不够会以1.5倍的容量增长
*查询快,增删数据效率会低
![223db1662a5da2cd36ca3a173699bab7.png](en-resource://database/662:0)
![e215b3f3fce0f18bd7c5214598412ed1.png](en-resource://database/664:0)

#### 4.2 创建对象
![7d9391fe2b6f5cb260f9f47bfa989b7b.png](en-resource://database/666:0)
package cn.tedu.list;

```
import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;

/**本类用于ArrayList相关测试*/
public class TestArrayList {
    public static void main(String[] args) {
        //1.创建对应的集合对象
        /**底层会自动帮我们创建数组来存放对象,并且数组的初始容量是10*/
        ArrayList<Integer> list = new ArrayList();

        //2.向集合中添加元素,用于测试
        list.add(100);
        list.add(200);
        list.add(300);
        list.add(400);
        list.add(400);
        list.add(300);
        System.out.println(list);

        //3.测试常用方法
        //list.clear();//清空集合
        //System.out.println(list);//[]

        //false,是否包含指定元素“100”,这是String不是Integer,不包含
        System.out.println(list.contains("100"));
        System.out.println(list.get(0));//100,根据下标获取元素
        System.out.println(list.indexOf(400));//3,判断指定元素第一次出现的位置
        System.out.println(list.lastIndexOf(400));//4,判断指定元素最后一次出现的位置
        
        System.out.println(list.remove(1));//200,移除指定位置处的元素
        //System.out.println(list.remove(300));
        /**上面的代码会报错:数组下标越界:index:300 size:5
         * 主要是因为List中有两个重载的remove(),如果传入的是300
         * 会认为是int类型的index索引,所以如果想指定元素删除数据
         * 需要把int类型的300手动装箱成Integer类型*/
        System.out.println(list.remove(Integer.valueOf(300)));
        
        System.out.println(list.set(2,777));//修改指定索引处的元素的值为777
        System.out.println(list.size());//获取列表中元素的个数

        //4.进行集合的迭代
        //方式1:for循环
        System.out.println("方式一:for循环迭代");
        for(int i = 0;i <= list.size()-1 ; i++){
            System.out.println(list.get(i));
        }
        //方式2:高效for循环
        System.out.println("方式二:高效for循环迭代");
        //for(本轮遍历到元素的类型 元素名 : 要遍历的集合名){循环体}
        for(Integer t : list){
            System.out.println(t);
        }
        //方式3:iterator迭代器
        System.out.println("方式三:iterator迭代器:");
        //获取迭代器对象
        Iterator<Integer> it = list.iterator();
        //循环迭代集合中的所有元素
        while(it.hasNext()){//判断是否有下一个元素可迭代,如果有,继续循环
            System.out.println(it.next());//打印本轮迭代到的元素
        }
        //方式4:listIterator
        System.out.println("方式四:list独有的迭代器listIterator");
        //获取迭代器对象
        ListIterator<Integer> it2 = list.listIterator();
        //循环迭代集合中的所有元素
        while(it2.hasNext()){//判断是否有下个元素可迭代
            System.out.println(it2.next());//打印本轮迭代到的元素
        }
    }
}

```

### 5 LinkedList
#### 5.1 概述链表,两端效率高,底层就是链表实现的
![90dc9281662f8d20844b7e8800d07290.png](en-resource://database/668:0)
![6f9a82c90d7ae72fc9d1934d40841c7b.png](en-resource://database/670:0)
![acb8efa4914d03a9353b8ba2214d1428.png](en-resource://database/672:0)
5.2 创建对象
LinkedList() 构造一个空列表

5.3 常用方法
```
void addFirst(E e) 添加首元素
void addLast(E e) 添加尾元素
E getFirst() 获取首元素
E getLast() 获取尾元素
E element() 获取首元素
E removeFirst() 删除首元素
E removeLast() 删除尾元素

boolean offer(E e) 添加尾元素
boolean offerFirst(E e) 添加首元素
boolean offerLast(E e) 添加尾元素
E peek() 获取首元素
E peekFirst() 获取首元素
E peekLast() 获取尾元素
E poll() 返回并移除头元素
E pollFirst() 返回并移除头元素
E pollLast() 返回并移除尾元素
public void push(E e):推送到链表开头(压栈)---等价于public void addFirst(E e):添加到链表的开头
 *          public E pop():弹出最后一个元素(弹栈) 等于removeFirst() :将第一个元素删除并返回
```

#### 5.4练习:LinkedList测试
package cn.tedu.colletion;
```

import java.util.LinkedList;

/**本类用于测试LinkedList的相关测试*/
public class TestLinkedList {
    public static void main(String[] args) {
        //1.创建对象
        LinkedList<String> list = new LinkedList();
        //2.添加数据
        list.add("孙悟空");
        list.add("猪八戒");
        list.add("唐三藏");
        list.add("沙师弟");
        list.add("白龙马");
        System.out.println(list);
        //3.1自行测试从collection继承过来的共性方法测试
        //3.2 LinkedList特有方法测试
        list.addFirst("蜘蛛精");//添加首元素
        list.addLast("玉兔精");//添加尾元素
        System.out.println(list);
        
        System.out.println(list.getFirst());//获取首元素
        System.out.println(list.getLast());//获取尾元素
        
        System.out.println(list.removeFirst());//移除首元素,成功移除会返回移除的数据
        System.out.println(list);
        System.out.println(list.removeLast());//移除尾元素,成功移除会返回移除的数据
        System.out.println(list);
        
        //4.其他测试
        //4.1创建对象
        LinkedList<String> list2 = new LinkedList();
        //4.2添加数据
        list2.add("水浒传");
        list2.add("三国演义");
        list2.add("西游记");
        list2.add("红楼梦");
        System.out.println(list2);
        System.out.println(list2.element());//获取但不移除此列表的首元素(第一个元素)
        /**别名:查询系列*/
        System.out.println(list2.peek());//获取但不移除此列表的首元素(第一个元素)
        System.out.println(list2.peekFirst());//获取但不移除此列表的首元素(第一个元素)
        System.out.println(list2.peekLast());//获取但不移除此列表的尾元素(最后一个元素)
        
        /**别名:新增系列*/
        System.out.println(list2.offer("遮天"));//将指定元素添加到列表末尾
        System.out.println(list2.offerFirst("斗罗大陆"));//将指定元素插入列表开头
        System.out.println(list2.offerLast("斗破苍穹"));//将指定元素插入列表末尾
        System.out.println(list2);
        
        /**别名:移除系列*/
        System.out.println(list2.poll());//获取并且移除此列表的首元素(第一个元素),成功移除,返回移除元素
        System.out.println(list2.pollFirst());//获取并且移除此列表的首元素(第一个元素),成功移除,返回移除元素,如果此列表为空,则返回null
        System.out.println(list2.pollLast());//获取并且移除此列表的尾元素(最后一个元素),成功移除,返回移除元素,如果此列表为空,则返回null
        System.out.println(list2);
    }
}
#### 6 扩展: ArrayList扩容
```
ArrayList相当于在没指定initialCapacity时就是会使用延迟分配对象数组空间,当第一次插入元素时才分配10(默认)个对象空间。假如有20个数据需要添加,那么会分别在第一次的时候,将ArrayList的容量变为10;之后扩容会按照1.5倍增长。也就是当添加第11个数据的时候,Arraylist继续扩容变为10*1.5=15;当添加第16个数据时,继续扩容变为15 * 1.5 =22个
ArrayList没有对外暴露其容量个数,查看源码我们可以知道,实际其值存放在elementData对象数组中,那我们只需拿到这个数组的长度,观察其值变化了几次就知道其扩容了多少次。怎么获取呢?只能用反射技术了。
```
![8680a99b31deecfe23bd634f509aadc8.png](en-resource://database/674:0)
![f20d450a5cc6c01b90a125c9853ee89a.png](en-resource://database/676:0)
#### 使用LinkedList的特有功能模拟栈结构特点?
```
栈结构:先进后出
package com.qf.linkedlist_03;

import java.util.LinkedList;

/**
 * @author 高圆圆
 * @date 2022/8/20 11:38
 *
 * 使用LinkedList的特有功能模拟栈结构特点?
 *       栈结构:先进后出
 *
 *      相当于自定义一个类,这个类完成一些功能,需要使用到LinkedList集合的特有功能
 *      这个功能添加元素(压栈)--->使用LinkedList的addFirst():每一次将元素添加到链表开头
 *      获取元素:(弹栈)----->使用LinkedList集合的removeFist():相当于pop:弹栈,删除第一个并获取第一个元素
 */
public class MyStack {

    //成员变量的位置
    private LinkedList linkedList ;
    //定义一个构造方法
    public  MyStack(){
        //创建一个LinkedList集合对象
        linkedList = new LinkedList() ;
    }

    //定义一个功能:添加元素的方法   压栈
    public void addElement(Object obj){ //添加任何Java类型  "hello","world"
        //间接用到LinkedList的特有功能
        linkedList.addFirst(obj); // "world","hello"使用linkedList就添加开头了
    }

    //定义一个功能,弹栈: 取出元素 ,将LinkedList集合第一个元素删除并返回
    public Object getElement(){
        return linkedList.removeFirst() ;//删除第一个并返回
    }

    //提供判断功能
    public boolean isEmpty(){
        return linkedList.isEmpty() ;
    }
}
```
package com.qf.linkedlist_03;

/**
 * @author 高圆圆
 * @date 2022/8/20 11:16
 *
 * 面试的编程题
 * 使用LinkedList的特有功能模拟栈结构特点?
 *      栈结构:先进后出
 *
 *     相当于自定义一个类,这个类完成一些功能,需要使用到LinkedList集合的特有功能
 *     这个功能添加元素(压栈)--->使用LinkedList的addFirst():每一次将元素添加到链表开头
 *     获取元素:(弹栈)----->使用LinkedList集合的removeFist():相当于pop:弹栈,删除第一个并获取第一个元素
 */
//测试类
```
public class Test {
    public static void main(String[] args) {

```

        //创建MyStack对象
        MyStack my = new MyStack() ;
        my.addElement("hello") ;
        my.addElement("world") ;
        my.addElement("javaEE") ;
        my.addElement("蔡徐坤");

        //获取元素
       /* //第一次获取
        if(!my.isEmpty()){
            Object element = my.getElement();
            System.out.println(element);
        }

        if(!my.isEmpty()){
            //第二次获取
            Object element2 = my.getElement();
            System.out.println(element2);
        }

        if(!my.isEmpty()){
            //第三次获取
            System.out.println(my.getElement());
        }

        if(!my.isEmpty()){
            //第四次获取
            System.out.println(my.getElement());
        }

        if(!my.isEmpty()){
            //第五次获取
            System.out.println(my.getElement());
        }*/

        while(!my.isEmpty()){//不为空,在获取
            System.out.println(my.getElement());
        }

    }
    

* * *


### 选择排序
```
import java.util.Arrays;

/**
 * @author 高圆圆
 * @date 2022/8/20 10:01
 *
 *创建一个数组
 *      int[] arr = {24,69,87,56,13} ;
 *      对这个数组首先遍历,在去排序(只是排序),再次遍历,展示排序后的数组内容!
 */
public class SelectSortDemo {
    public static void main(String[] args) {

        //创建一个数组,静态初始化
        int[] arr = {24,69,87,56,13} ;

        System.out.println("排序前:");
        //调用遍历数组的功能
        //printArray(arr);

        //数组工具类:Arrays.toString(任意类型的数组)---转成String
        System.out.println(Arrays.toString(arr)) ;
        System.out.println("---------------------------------") ;
        //将上面的代码进行优化,因为上面的代码冗余度太大了
        //外层循环:比较的次数:比较次数数组长度-1次
        for(int x = 0 ; x < arr.length-1; x++){
            for(int y = x+1; y < arr.length ; y++){
                //元素比较,要进行判断,前面的元素和后面元素比较
                if(arr[x] > arr[y]){
                    int temp = arr[x] ;
                    arr[x]  = arr[y] ;
                    arr[y] = temp ;
                }
            }
        }
        System.out.println("排序后:") ;
        System.out.println(Arrays.toString(arr));

        System.out.println("--------------------------------------------") ;
        //使用方法改进,返回排序后的数组对象
        int[] arr2= selectSort(arr) ;
        System.out.println(Arrays.toString(arr2));
    }
    //选择排序的方法
    public static int[] selectSort(int[] arr){
        for(int x = 0 ; x < arr.length-1; x++){
            for(int y = x+1; y < arr.length ; y++){
                //元素比较,要进行判断,前面的元素和后面元素比较
                if(arr[x] > arr[y]){
                    int temp = arr[x] ;
                    arr[x]  = arr[y] ;
                    arr[y] = temp ;
                }
            }
        }
        return  arr ;
    }
    //自定义的方法
    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]+", ");
            }
        }
    }
}
```
## set集合
package com.qf.set_04;

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

/**
 * @author 高圆圆
 * @date 2022/8/20 11:58
 * Set集合的特点:保证元素唯一,而且不能保证迭代次序
 *                  唯一,无序性(元素不重复,不能保证顺序---哈希表(key-value键值对)完成的(桶状结构))
 *
 *         创建HashSet(Set接口的子实现类之一)集合对象来存储String类型,重复的数据,看效果
 *
 *
 *         为什么保证元素能唯一的:
 *         HashSet底层依赖于Map<K,V>接口的子实现类HashMap<K,V>实现的
 *
 *         HashSet的add()方法依赖于HashMap的put 方法,这个方法间接依赖于Object类的equals和hashCode()
 *         而现在存储String类型,String底层已经重写了hashCode()和equals方法
 *         HashCode:比较字符串的哈希码值(理解为地址值)是否一样,如果一样,比较内容是否一样
 *              英文可以,但是中文,繁写字体或简写字体,hashCode一样,内容可能不一样;必须重写equals,比较内容是否相容!
 * HashSet<Student>如果存储的是自定义对象,必须自定义的类要重写Object类的equals和hashCode(),否则不是唯一的
 *
 */
```
public class HashSetDemo {
    public static void main(String[] args) {
        //创建HashSet集合对象
        Set<String> set = new HashSet<>() ;//String---->jdk提供的类

        //添加元素
        set.add("hello") ;
        set.add("hello") ;
        set.add("javaEE") ;
        set.add("world") ;
        set.add("world") ;
        set.add("android") ;
        set.add("android") ;
        set.add("python") ;
        set.add("python") ;

        //遍历增强for
        for(String s:set){
            System.out.println(s) ;
        }
    }
}
package com.qf.vector_02;

import java.util.Enumeration;
import java.util.Vector;
```
### vector集合
```
/**
 * @author 高圆圆
 * @date 2022/8/20 10:46
 * Vector集合底层数据结构数组,是List集合接口子实现类之一,遍历元素能够List的五种方式
 * 但是它有自己的特有功能
 *      添加元素
 *              public void addElement(E obj):添加任意元素 如果E类型确定了,就只能添加这个数据类型
 *                          类似于  集合的通用功能add(E obj)
 *      遍历元素方式1
 *              public Enumeration<E> elements():获取组件(返回值是枚举接口---产生一系列元素)
 *                          类似于Collection集合的Iterator iterator()迭代器
 *                      Enumeration枚举接口
 *                              boolean hasMoreElements()  判断是有更多的元素
 *                                          --->类似于Iterator迭代器里面的hasNext()
 *                              E nextElement() :获取下个元素
 *                                          --->类似于Iterator迭代器里面的next():获取下一个元素
 *      遍历元素方式2
 *
 *              public E elementAt(int index)通过角标获取元素 ---类似于List集合的public E get(int index)
 *              结合 int size()获取集合长度(集合元素数量)
 *
 * 这个集合特点:底层数据结构数组(查询,更新元素比较快,添加,删除比较麻烦的),
 * 线程安全的类---同步的---执行效率比较低(多线程环境下使用安全性比较大的类)
 *
 *
 */
public class VectorDemo {
    public static void main(String[] args) {

        //创建Vector集合对象
        Vector<String> v = new Vector<>() ;

        //添加元素
        //public void addElement(E obj):添加任意元素 如果E类型确定了,就只能添加这个数据类型
        v.addElement("hello");
        v.addElement("world");
        v.addElement("JavaEE");
        v.addElement("高圆圆");

        //特有遍历方式1;
//        public Enumeration<E> elements():获取组件(返回值是枚举接口---产生一系列元素)
//        类似于Collection集合的类似于Collection集合的Iterator iterator()迭代器
        Enumeration<String> enumeration = v.elements();
        /**
         *  Enumeration枚举接口
         *                           boolean hasMoreElements()  判断是有更多的元素
         *                                        --->类似于Iterator迭代器里面的hasNext()
         *                              E nextElement() :获取下个元素
         *                                         --->类似于Iterator迭代器里面的next():获取下一个元素
         */
        while(enumeration.hasMoreElements()){ //判断是否有更多的元素
            String s = enumeration.nextElement();
            System.out.println(s);
        }

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

        //特有方式2
        //public E elementAt(int index)通过角标获取元素 ---类似于List集合的public E get(int index)
        //结合 int size()获取集合长度(集合元素数量)
        for(int x = 0 ; x < v.size(); x++){
            //通过角标获取元素
            String s = v.elementAt(x);
            System.out.println(s);
        }

        System.out.println("--------------------------------------------------" ) ;
        //最终归结于增强for
        for(String s:v){
            System.out.println(s);
        }
    }
}
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值