java08 数组与集合

1 数组的定义与规范

一个变量只能存放一个数据,一个数组是一个容器,可以存放多个数据

数组的特点

1 数组是一种引用数据类型

2 数组中的多个数据,类型必须统一

3 数组的长度在程序运行期间,不可改变


数组的初始化

1 动态初始化  指定长度:  数据类型[] 数组名称 = new 数据类型 [ 数组长度]

左侧的数据类型  表示数组中保存的数据类型

左侧的中括号      代表我是一个数组

左侧的组名称     给数组取一个名字

右侧的new  代表创建数组的动作

右侧的数据类型 必须和左边的数据类型保存一直

右侧的括号长度 标书数组中,存放多少个数据,是一个int数字

public class HelloWorld2 {
    public static void main(String[] args) {
        int[] a = new int[1];
        float[] b = new float[2];
        double[] c = new double[3];

    }
}

2 静态初始化  指定内容: 数据类型[] 数组名称 = new 数据类型 [ ]{元素1,元素2,,,,}

public class HelloWorld2 {
    public static void main(String[] args) {
        int[] a = new int[]{1,2,3,4,5,6,7,0};
    }
}

虽然静态初始化没有给定长度,但可以根据大括号的元素格式,推算出数组长度

3 省略静态初始化  数据类型[]  数组名称 = {1,2,3,4,5,6,7,9}

说明:

静态初始化,没有直接指定长度,仍然可以推算出长度

静态初始化标准格式可以拆分为两个步骤,但省略的静态初始化不可以

动态标准化也可以拆分2个步骤

public class HelloWorld2 {
    public static void main(String[] args) {
        int [] a;
        a = new int[5]
    }
}

5C2DFCD9-82E1-4449-926A-822588C87D13


使用区别  已知内容使用静态,指定长度使用动态

2 数组的各种方法

2.1 指定打印数组名称  输出的是数组的内存地址

public class HelloWorld2 {
    public static void main(String[] args) {
        int [] a;
        a = new int[5];
        System.out.println(a);
    }
}
结果 [I@1b6d3586


2.2.指定数组,访问数组的具体元素-数组索引自 0  到   n -1

public class HelloWorld2 {
    public static void main(String[] args) {
        int [] a = new int[]{10,20,30};
        System.out.println(a[0]);
    }
}
结果 10

2.3 访问指定数组元素,并赋值。

使用动态初始化数组的时候,其中的元素将会自动拥有一个默认值

1)如果是整数类型,那么默认0

2)如果是浮点类型,那么默认0.0

3)如果是字符类型,那么默认为\u0000

4)如果是布尔类型,那么默认为false

5)如果是引用类型,那么默认为null

使用静态初始化数组的时候,也有默认值,只不过迅速变成了指定值

public class HelloWorld2 {
    public static void main(String[] args) {
        int [] a = new int[]{10,20,30};
        System.out.println(a);
        System.out.println(a[0]);
        System.out.println(a[1]);
        System.out.println(a[2]);
        int [] b = new int[3];
        System.out.println(b);
        System.out.println(b[0]);
        System.out.println(b[1]);
        System.out.println(b[2]);
    }
}
结果

[I@1b6d3586
10
20
30
[I@4554617c
0
0
0

2.3 访问指定数组元素,并赋值。

public class HelloWorld2 {
    public static void main(String[] args) {
        int [] a = new int[]{10,20,30};
        System.out.println(a);
        System.out.println(a[0]);
        System.out.println(a[1]);
        System.out.println(a[2]);
        System.out.println("------------");
        a[1] = 123;
        System.out.println(a[1]);
    }
}

结果
[I@1b6d3586
10
20
30
------------
123

2.5 java内存分布

java内存分为5个部分

1)栈内存 stack 存放的是方法中的局部变量;

      局部变量:方法中的参数,或者是方法{}内部变量;

      作用域    :一旦超出作用域,立刻从栈中消失

2)堆内存 heap 凡是new出来东西,都在堆中;

       堆内存里面的东西,都有一个地址,16进制;

       堆内存里面的数据,都有默认值,如下:

               如果是整数,默认为0

               如果是浮点数 默认为0.0

               如果是字符,默认为 \u0000

               如果是布尔    默认为false

                如果是引用类型 默认为null

3)方法区 method area  存储class相关信息,包含方法的信息

4)本地方法栈(native method stack) 与操作系统相关

5)寄存器(PC register) 与CPU相关

6)两个数组指向同一个地址时,其中一个数组修改,另一个数组值也将修改

3EF55A90-62F7-41c6-B020-D79B76681DA0

数组常见错误

1)数组长度的越界;

2)数组必须new初始化,才能使用其中元素,或者对于引用类型变量,赋值为null,否则会引起空指针异常。

33F557FA-945A-4639-864D-DD15C0446B2F

2.6 数组的方法

1)数组的长度: 数组名称.length;即可

A8DDE522-1626-4995-83CF-32FBD086ADB7

2) 数组的遍历

指定一个数组

31DF9453-D7B0-4ddb-9841-C37A04A5846A

使用另外一种方式,数组长度。length,可以使用for循环

public class HelloWorld2 {
    public static void main(String[] args) {
        int [] b = {1,2,3,4,5,6,7,88,8};
        int len = b.length;
        for (int i = 0; i <len ; i++) {
            System.out.println(b[i]);
        }
    }
}

3)数组的最大值

使用变量获取最大值,循环比较

BFD5D13D-CA83-461f-972C-DECA8FA8F061

4)数组的反转

    数组的元素反转,要么定义新数组,要么数组的自我反转(对称位置的反转)

5)数组作为方法参数

     有时候,我们需要对数组进行无数次遍历

A2CC3794-65F6-4d31-8223-01D12F08D35F

我们可以定义一个方法,来实现这个动作

8023AF6E-B1C3-45ab-A0C1-FFC920E3AAB6

运行结果如下:


E534E7B5-6C76-44d3-9E5D-3C8DEC560F68

6)数组作为方法返回值


任何数据类型,都可以作为方法的返回值

一个方法可以有多个参数,但是只能有0,1,不能有多个返回值;

如果希望一个方法当中产生了多个结果数据进行返回,怎么办

解决方案 使用一个数组作为返回值类型即可


数组作为方法的返回值,返回的是地址值


2B52A8DE-3188-4cc7-9F41-53494DE27467

3 集合

集合和数组都是容器,主要区别在

1)数组长度是固定的,集合长度是可变;

2)数组可以存在数据和对象,而集合存储的都是对象(可不同类型)

3.1 集合框架

集合按照存储结构,分为两大类,单列集合(java.util.Collection)和双列集合(java.util.Map),现在独立学单列集合java.util.Collection.

单列集合java.util.Collection 用于存储一系列符合某种规则的元素,它有两个重要的子接口分别是 java.out.List和java.util.Set,

其中List是元素有序,元素可重复,主要实现的类有java.util.ArrayList和java.util.LinkedList.

其中Set是元素无序,而且不可重复。主要实现的类有java.util,HashSet 和java.util.TreeSet.

5DA99A72-B16B-4192-B634-840842D9F2FD

8B4B5AD1-7F03-4c7a-BA45-689F7989ECAB

3.2Collection集合功能

Collection是所以单列集合的父几口,因此在Collection中定义了单列集合通用的一些方法,可以用在操作所有

9878C2B6-7E67-4866-B7BF-52B8122B36A9




4 迭代器

每种集合存储信息不同,对于Collection集合元素的通用存取方法,在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续再【判断。如果还有就再取出来,一直把集合中的所有元素全部取出,这种取出方式的专业术语叫迭代。

4.1 Iterator接口

java.util.Interator接口:迭代器

boolean hasNext()如果还有元素可以迭代,就返回true

判断集合中还有没有下一个元素,有就true 没有就false

E next()返回迭代的下一个元素,取出集合中的下一个元素。

迭代器的使用步骤

1 使用集合中的方法iterator获取迭代器的实现类对象,使用Iterator接口接受(多态)

2使用Iterator接口中的方法hasNext()判断还有没有下一个元素

3使用Iterator接口中的法法Next()取出集合中下一个元素

A9C734BB-1F3F-4ae7-8B2C-5961A67D2243

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

//定义一个方法,求出1-100之间的和
public class HelloWorld2 {
    public static void main(String[] args) {
        //创建一个集合对象
        Collection<String>  coll = new ArrayList<>();
        //往集合对象中添加元素
        coll.add("哈哈1");
        coll.add("哈哈2");
        coll.add("哈哈3");
        coll.add("哈哈4");
        //多态 接口 实现类对象
        Iterator<String> it = coll.iterator();
        // 发现使用迭代器取出集合中元素的代码,是一个重复的过程
        //所以我们使用循环化
        //不知道集合中有多少对象,使用while循环
        // 循环结束,hasNext方法返回false
        while(it.hasNext()){
            String e = it.next();
            System.out.println(e);
        }
    }
}

增强for循环

B6F24C85-81D4-4cdf-9569-53CDF020A1C4

5 泛型

前面学习集合时,我们都知道集合中是可以存放任意对象的,只要把对象存储集合后,那么这时他们都会被提升成Object类型,当我们在取出每一个对象时,并且进行相应的操作,这时必须采用类型转换、。


泛型是一个未知的数据类型,当我们不知道使用什么数据类型的时候,可以用泛型, 泛型也可以看出是一个变量,用来接收数据类型。

E e Elemant元素

T t Type类型

以集合ArrayList为例,ArrayList集合定义时候,不知道会存储什么类型的数据,所以类型使用泛型,E 未知的数据类型。

C4A12B16-4456-41d8-932E-E312EEA8E458

那么类型什么时候能够确定,创建集合对象的时候,就会确定=泛型的数据类型

EFF26C40-BCCE-4038-BA28-C3F9754D8AA1

会把数据类型作为参数传递,把String赋值给泛型E。

E55241C5-A41E-45ad-BB1B-99394E755E2B

使用案例表达下使用泛型与不使用泛型的区别

1  集合不使用泛型,默认类型是Object类型,可以存储任意类型数据,迭代器的泛型是跟着集合走,集合没有泛型,那么迭代器也就没有泛型。

    弊端 不安全,会引发异常

import java.util.ArrayList;
import java.util.Iterator;

/*
创建对象,不使用泛型
好处: 集合不使用泛型,默认类型就是Object类型,可以存储任意类型的数据
弊端   不安全,容易引发异常
 */
class hellword2{
    public static void main(String[] args) {
        show1();
    }


    private static void show1(){
        ArrayList list = new ArrayList();
        list.add("abc");
        list.add("1");
        // 使用迭代器遍历list集合
        //获取迭代器
        Iterator it = list.iterator();
        //使用迭代器中的方法hasNext 和 next遍历集合
        while(it.hasNext()){
            //取出元素也是Object类型
            Object obj = it.next();
            System.out.println(obj);
            //使用string类特有的方法,length获取字符串的长度,
            //多态的弊端,不能使用子类的方法。
            //需要向下转型。
            String s = (String)obj;
            System.out.println(s.length());
            }
        }
}
结果
abc
3
1
1

2 集合使用泛型,避免了类型转换的麻烦,存储是什么类型,取出就是什么类型,同时运行异常,提升到了编译期间(代码编写时候,提醒错误)

      弊端,泛型是什么类型, 只能存储什么类型。

import java.util.ArrayList;
import java.util.Iterator;

/*
创建对象,不使用泛型
好处: 集合不使用泛型,默认类型就是Object类型,可以存储任意类型的数据
弊端   不安全,容易引发异常
 */
class hellword2{
    public static void main(String[] args) {
        show1();
        show2();
    }
    public static void show2(){
        ArrayList<String> list = new ArrayList<>();
        list.add("123");
        list.add("456");
        //使用迭代器遍历list集合
        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            String s = it.next();
            System.out.println(s);

        }
    }


    private static void show1(){
        ArrayList list = new ArrayList();
        list.add("abc");
        list.add("1");
        // 使用迭代器遍历list集合
        //获取迭代器
        Iterator it = list.iterator();
        //使用迭代器中的方法hasNext 和 next遍历集合
        while(it.hasNext()){
            //取出元素也是Object类型
            Object obj = it.next();
            System.out.println(obj);
            //使用string类特有的方法,length获取字符串的长度,
            //多态的弊端,不能使用子类的方法。
            //需要向下转型。
            String s = (String)obj;
            System.out.println(s.length());
            }
        }
}

5.泛型的定义和使用

我们在集合中会大量使用到泛型,泛型用来灵活的将数据类型应用到不同的类,方法和接口当中,将数据类型作为参数进行传递。

1定义和使用含有泛型的类

定义格式

   修饰符  class 类名<代表泛型的变量>{}

例如:API 中的ArrayList集合:

class ArrayList<E>{
    public boolean add(E e){}
    public E get(int index){}
}
public class nohello {
    public static void main(String[] args){
        //创建helloworld2的对象
        helloworld2 gc = new helloworld2();
        gc.setName("只能是字符串");
        String name = gc.getName();
        System.out.println(name);
    }
}

C6067FFE-5285-4912-9FAB-2D2569782922

9A4B40AC-0D68-4d84-8584-13B1DD542FB1

6C410086-A781-442d-98A2-EFA53B9BA211








posted @ 2019-04-16 14:31  芒果侠  阅读(239)  评论(0编辑  收藏  举报