JavaSE06-集合

集合

Collection接口

概述

数组和集合都是Java中提供的容器

集合: 英文译为 Collection,用来存放对象的容器,集合中可以存放不同类型的对象,并且集合的长度可变。

在编程时,常常需要集中存放多个数据,可以使用数组来保存多个对象,但数组长度不可变化,一旦在初始化数组时指定了数组长度,这个数组长度就是不可变的,如果需要保存数量变化的数据,数组就有点无能为力了;

为了保存数量不确定的数据,以及保存具有映射关系的数据,Java提供了集合类。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类。

小结: 集合和数组的对比:

1)数组中的元素可以基本类型的值,也可以是对象; 而集合中只能保存对象

2)数组一旦指定了长度,长度就不能再改变; 而集合的长度是可以随时改变的

3)往数组中插入元素非常麻烦,需要将插入位置后面的元素往后移动; 或者删除数组中间位置的某一个元素, 需要将删除位置后的元素往前移动; 而如果往集合中插入元素或者删除集合中的某一个元素,直接使用现成的方法操作即可

集合的继承结构

由于需求不同,Java就提供了不同的集合类。这多个集合类的数据结构不同,但是它们都是要提供存储和遍历功能的,我们把它们的共性不断的向上提取,最终就形成了集合的继承体系结构图。

Collection接口

|-- List接口

​ |-- ArrayList类

​ |-- LinkedList类

|-- Set接口

​ |-- HashSet类

​ |-- TreeSet类

解释说明:

- Collection集合是所有单值集合的顶层接口, 其中定义了常用的用于操作集合以及集合中元素的方法

例如: 添加元素、删除元素、获取元素、获取集合长度、判断功能、将集合转成数组、迭代器遍历元素等功能

- List是Collection的子接口,特点是其中的元素是有序的(即:元素存入集合时的顺序和取出的顺序一致)

可以通过下标访问List中的元素,另,List集合中的元素是可以重复的(包括null)

- Set也是Collection的子接口,特点是其中的元素是无序(即:元素存入集合时的顺序和取出的顺序不一定一致)

无法通过下标访问Set中的元素,另外,Set集合中的元素是不可以重复的

学习集合的建议:

- 学习接口中提供的共性方法

- 通过实现类创建对象, 调用这些共性方法

常用方法

​ !!boolean add(E e)

​ – 往集合中添加指定元素e

​ boolean addAll(Collection c)

​ – 将小集合添加到大集合中

​ !!boolean isEmpty()

​ – 如果集合中没有任何元素(空集合), 返回true

​ boolean contains(Object o)

​ – 如果此集合中包含指定元素o, 则返回true

​ boolean containsAll(Collection c)

​ – 如果此集合中包含指定 集合c 中的所有元素,则返回 true。

​ – 例如c1中有 “a”,“b”,“c”,“d”, 而c2中有"a",“b”, 则c1包含c2, 返回true

​ 若,c1中有 “a”,“b”,“c”,“d”, 而c2中有"x",“a”,“b”, 则c1不包含c2, 返回false

​ !!int size()

​ – 返回集合的大小(元素个数)

​ !!boolean remove(Object o)

​ – 从集合中删除指定的元素o, 删除成功则返回true

​ – 如果删除的元素不存在导致删除失败, 则返回false

​ – 如果元素o在集合中出现多次,仅删除第一个

​ boolean removeAll(Collection c)

​ – 删除此集合中那些也包含在指定集合c中的所有元素, 若有共同元素, 则删除并返回true

​ 例如 c1中有 “a”,“b”,“c”,“d”, 而c2中有"x",“a”,“b”,

​ c1.removeAll(c2),只删除c1中两个共同的元素 “a”,“b”, 对c2没有影响

​ – 如果两个集合中没有共同元素, 则不删除, 返回false

boolean retainAll(Collection c)

​ – 仅保留此集合中那些也包含在指定集合c中的元素

​ 例如 c1中有 “a”,“b”,“c”,“d”, 而c2中有"x",“a”,“b”,

​ c1.retainAll(c2),只保留c1中两个共同的元素 “a”,“b”, 对c2没有影响

​ void clear()

​ – 删除此集合中的所有元素

​ Object[] toArray()

​ – 将此集合转成对象数组

​ boolean equals(Object o)

​ – 比较此 collection 与指定对象是否相等。

​ !!Iterator iterator()

​ – 返回此集合中所有元素组成的迭代器。

实例1:CollectionDemo1

package Part06Collection;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;

/**
 * JAVA集合框架
 * 集合和数组一样的,都是用来存储一组元素,但是集合将元素的操作都封装成了方法,操作简单
 * 并且集合还提供了多种不同的实现供我们使用
 * java.util.Collection是所有集合的顶级接口,里面定义了所有的集合的必须具备的功能
 * 集合相比数组的优点:1.不需要指定长度,存储的内容随意个2.存储的类型可以任意
 * 集合中常用的两个子类:
 * java.util.List:可重复的集合,且有序.通常被称之为'线性表'
 * java.util.Set:不可重复的集合
 * 上述两个都是接口
 */
public class CollectionDemo1 {
    public static void main(String[] args) {
        //集合中只能存放引用类型
        Collection c = new ArrayList();
        /*
         * add:加
         * boolean add(E e) 这个E是泛型,这里就先理解为时Object
         * 向当前集合中添加一个元素,如果元素添加成功,会返回一个true,否则返回false
         */
        c.add("one");
        c.add("two");
        c.add("three");
        c.add("four");
        c.add("five");
        c.add(123);//c.add(Integer.valueOf(123)) 会触发自动装箱特性
        System.out.println(c);//[one, two, three, four, five]
        /*
         * int size()
         * 返回当前集合的元素个数
         * 区别于数组的length,数组的length表示数组能存多少,但是存不够,长度也这么长
         * 但是size不是,size表示集合中有几个元素个数
         * 那这个方法返回的是int,所以集合返回的int的最大值,就是集合中能存储的最大个数嘛?
         * 集合中可以存储更多的元素
         * size: 尺寸,大小
         */
        int size = c.size();
        System.out.println("集合的元素个数:"+size);
        /*
         * empty: 空的
         * boolean isEmpty()
         * 判断当前集合是否为空集合,当size为0时,返回true
         */
        boolean isEmpty = c.isEmpty();
        System.out.println("集合是否为空:"+isEmpty);
        //清空集合 把集合变为空集合
        c.clear();
        System.out.println(c);
        System.out.println("集合的元素个数:"+c.size());
        System.out.println("集合是否为空:"+c.isEmpty());
    }
}

实例2:CollectionDemo2

package Part06Collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;

public class CollectionDemo2 {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        //Collection c = new HashSet();//不可以重复存储相同的元素
        c.add(new Point(1, 2));
        c.add(new Point(3, 4));
        c.add(new Point(5, 6));
        c.add(new Point(7, 8));
        c.add(new Point(9, 0));
        c.add(new Point(1, 2));
        /*
         * 集合中重写了toString(),格式为:
         * [元素1.toString(),元素2.toString(),元素3.toString(),...]
         * 所以如果输出的集合中的元素对象需要指定格式,需要对应类重写toString方法
         */
        System.out.println(c);
        Point p = new Point(1, 2);
        /*
         * boolean contains(Object o)
         * 判断当前集合是否包含给定元素
         * 元素是否包含取决于当前给定元素与集合中的元素的equals方法比较后,
         * 是否结果为true
         * 默认equas是比较内存地址的,如果需要按照指定的元素的值比较,
         * 可以重写该类的equals方法
         */
        boolean contains = c.contains(p);
        System.out.println("当前集合是否包含该元素:"+contains);
        /*
         * remove方法删除元素
         * 删除时,也是会和集合中的元素使用equals比较,如果是true可以删除
         * 对于List而言,可以存储重复的元素,对这种情况,仅会删除一次
         */
        c.remove(p);
        System.out.println(c);
    }
}
Point
package Part06Collection;

import java.util.Objects;

public class Point {
    private int x;
    private int y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
    @Override
    public String toString() {
        return "Point{" +
                "x=" + x +
                ", y=" + y +
                '}';
    }
    //alt+insert 选择equals and hashCode,然后一路回车即可
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return x == point.x && y == point.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
}

实例3:CollectionDemo3

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZXhVxuU-1654135210710)(pic/image-20220521094249618.png)]

package Part06Collection;

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

public class CollectionDemo3 {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        Point p = new Point(1, 2);
        c.add(p);//将p元素添加到集合中
        System.out.println("p:"+p);
        System.out.println("c:"+c);

        p.setX(2);//将p对象的x属性修改为2
        System.out.println("p:"+p);
        System.out.println("c:"+c);
    }
}

实例4:CollectionDemo4

package Part06Collection;

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

/**
 * 集合间的操作
 */
public class CollectionDemo4 {
    public static void main(String[] args) {
        Collection c1 = new ArrayList();
        c1.add("java");
        c1.add("c++");
        c1.add(".net");
        System.out.println("c1:"+c1);
        Collection c2 = new ArrayList();
        c2.add("android");
        c2.add("ios");
        c2.add("java");
        System.out.println("c2:"+c2);
        /*
         * boolean addAll(Collection c)
         * 将给定的集合中的所有元素添加到当前的集合中(取并集)
         * 操作后,当前集合发生了变化则返回true
         */
        boolean b = c1.addAll(c2);
        System.out.println(b);
        System.out.println("c1:"+c1);
        System.out.println("c2:"+c2);
        Collection c3 = new ArrayList();
        c3.add("c++");
        c3.add("java");
        //c3.add("php"); //不加php,就返回true,加了php,就返回false
        /*
         * boolean containsAll(Collection c)
         * 判断当前集合中是否包含给定集合中的所有元素
         */
        boolean b1 = c1.containsAll(c3);
        System.out.println("包含所有:"+b1);
        /*
         * 取交集 将两个集合中都有的元素进行保留
         */
        c1.retainAll(c3);
        System.out.println("c1:"+c1);
        System.out.println("c3:"+c3);
        /*
         * 删除交集. 将c1与c3的共有元素删除(c3不受影响)
         */
        c1.removeAll(c3);
        System.out.println("c1:"+c1);
        System.out.println("c3:"+c3);
    }
}

集合的遍历

IteratorDemo

package Part06Collection;

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

/**
 * 集合的遍历
 * Collection层面不支持随机访问操作(根据指定的位置获取对应的元素)
 * 但是集合支持遍历操作,我们可以通过遍历集合的方式拿到集合中的每一个元素
 *                      die
 * 集合提供了统一的遍历方式:迭代器遍历
 * 对应方法:
 * Iterator iterator()
 * 该方法会返回一个用于遍历当前集合的迭代器
 * java.util.Iterator是迭代器的接口,定义了迭代器遍历集合的基本操作,
 * 所有的集合都提供了一个变量自身元素的迭代器实现类,我们无需记住他们的名字,
 * 统一将他们都看做是Iterator即可.迭代器遍历集合遵循的步骤:问->取->删.
 * 其中删除不是必须的步骤
 */
public class IteratorDemo {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add("one");
        c.add("#");
        c.add("two");
        c.add("#");
        c.add("three");
        c.add("#");
        c.add("four");
        c.add("#");
        c.add("five");
        System.out.println(c);
        //获取迭代器对象
        Iterator it = c.iterator();
        /*
         * boolean hasNext()
         * 判断集合是否还有"下一个"元素可以遍历,迭代器的起始位置可以理解为是
         * 集合第一个元素的前一个,因此第一次调用hasNext方法就是来判断是否有第一个元素
         * E next()
         * 获取集合的"下一个元素",获取后迭代器的位置向后移动一个位置
         */
        while (it.hasNext()){
            String e = (String) it.next();
            System.out.println(e);
            if("#".equals(e)){
                /*
                 * 迭代器在遍历的过程中,不能通过集合的方法来增删元素,否则迭代器
                 * 会抛出并发修改异常
                 */
                //c.remove(e);
                /*
                 *  迭代器提供了remove方法可以将本次next获取的元素从集合中删除
                 */
                it.remove();
            }
        }
        System.out.println(c);
    }
}

增强型for循环

NewForDemo

package Part06Collection;

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

/**
 * JDK5推出时,推出了一个新特性:增强型for循环
 * 通常也称之为叫做新循环
 * 新循环不能取代传统for循环的工作,它的出现仅仅只是为了使用相同的语法遍历集合或者数组
 * 语法:
 * for(元素类型 e : 集合或者数组){
 *
 * }
 */
public class NewForDemo {
    public static void main(String[] args) {
        String[] array = {"one","two","three","four","five"};
        //传统for循环遍历数组
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
        //新循环遍历数组 array.for
        for (String s : array){
            System.out.println(s);
        }
        Collection<String> c = new ArrayList();
        c.add("一");
        c.add("二");
        c.add("三");
        c.add("四");
        c.add("五");
        for (Object o : c){
            String str = (String)o;
            System.out.println(str);
        }
        //新循环底层遍历就是迭代器遍历,编译器会将其改回迭代器遍历,
        //所以我们如果想删除集合中的元素时,这种新循环就不适合了
        for (String s : c) {
            System.out.println(s);
        }
    }
}

List集合

概述

List是一个有序的Collection(List是Collection的子接口),使用此接口能够精确的控制每个元素插入的位置,能够通过索引(类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。

List 接口存储一组可重复、有序(插入顺序)的对象。

特点

  1. 元素有下标,可以通过下标访问元素

  2. 元素是有序的(存入集合的顺序和取出的顺序一定相同)

  3. 元素可以重复(包括null)

List方法测试

ListDemo
package Part06Collection;

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

/**
 * java.util.List接口
 * List继承自Collection,是最常用的一类集合,特点:可以存放重复元素且有序
 * List里提供了一套可以通过下标操作元素的方法.
 * 常用的实现类:
 * java.util.ArrayList: 内部使用的数组实现,查询性能好
 * java.util.LinkedList: 内部使用的链表实现,增删性能好,收尾增删性能最佳
 * 对性能没有苛刻要求下,通常还是使用ArrayList即可
 */
public class ListDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("four");
        list.add("five");
        System.out.println(list);
        //获取集合中的第三个元素
        /*
         * E get(int index)
         * 获取指定的下标处对应的元素
         * 下标起始值是0
         */
        String str = list.get(2);//与数组获取元素的功能一致 String str = arr[2]
        System.out.println(str);
        //由于list集合有下标,所以可以使用for循环遍历
        for (int i = 0; i < list.size(); i++) {
            String s = list.get(i);
            System.out.println(s);
        }
        /*
         * E set(int index,E e)
         * 将给定元素设置到指定位置上,返回值是该位置原来的元素
         * 替换元素的操作
         */
        //[one, six, three, four, five]
        String old = list.set(1, "six");//将第二个位置原来的two替换为six,并将two返回
        System.out.println(old);
        System.out.println(list);
        //在不创建新的集合的前提下,将集合元素翻转
        /*
         *  one, six, three, four, five
         *  five,four,three, six ,  one
         *  0     1    2    3       4
         * 当0换到4
         * 当1换到3
         */
        for (int i=0;i<list.size()/2;i++){//i:0 1
            //获取正数位置上的元素
            String e = list.get(i);//one
            //将获取到的正数位置的元素替换到倒数位置上
            e = list.set(list.size()-1-i, e);
            //将原倒数位置上的元素替换到正数位置上
            list.set(i, e);
        }
        System.out.println(list);
        Collections.reverse(list);//翻转集合
        System.out.println(list);
    }
}
ListDemo2
package Part06Collection;

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

/*
 * List重载了一对add,remove方法
 */
public class ListDemo2 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("一");
        list.add("二");
        list.add("三");
        list.add("四");
        list.add("五");
        System.out.println(list);
        /*
         * void add(int index,E e)
         * 给指定元素插入到指定位置
         * 区别于set方法,set方法是覆盖
         */
        list.add(3,"老六儿");
        System.out.println(list);
        /*
         * E remove(int index)
         * 删除并返回指定位置上的元素
         */
        String old = list.remove(2);
        System.out.println(old);
        System.out.println(list);
    }
}
ListDemo3
package Part06Collection;

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

/**
 * List集合提供的方法:
 * List subList(int start,int end)
 * 获取当前集合的制定范围内的子集
 */
public class ListDemo3 {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        //向集合中添加0-9的元素
        for (int i=0;i<10;i++){
            list.add(i);
        }
        System.out.println(list);
        //获取子集[3-7] 含头不含尾
        List<Integer> sub = list.subList(3, 8);
        System.out.println(sub);
        //将子集中的每个元素都扩大10倍
        for (int i = 0; i < sub.size(); i++) {
            sub.set(i, sub.get(i)*10);
        }
        System.out.println(sub);
        //对子集的操作就是对原集合对应元素的操作
        System.out.println(list);
        //清除集合中1-8这部分元素
        list.subList(1, 9).clear();
        System.out.println(list);
    }
}

集合和数组的转换

集合转换数组:CollectionToArrayDemo
package Part06Collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;

/**
 * 集合转换为数组
 * Collection中定义一个方法toArray,可以将一个集合转换为一个数组
 */
public class CollectionToArrayDemo {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<>();
        c.add("老大");
        c.add("二娃");
        c.add("三弟");
        c.add("四兄");
        c.add("五妹");
        System.out.println("集合:"+c);
        //Object[] array = c.toArray();
        //需要传入一个指定长度的对应类型的数组
        String[] array = c.toArray(new String[c.size()]);
        System.out.println("数组:"+ Arrays.toString(array));
    }
}
数组转换集合: ArrayToListDemo
package Part06Collection;

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

/**
 * 数组转换为List集合
 * 数组的工具类Arrays提供了一个静态的方法asList,可以将一个数组转换为
 * 一个List集合
 */
public class ArrayToListDemo {
    public static void main(String[] args) {
        String[] array = {"one","two","three","four","five"};
        System.out.println("数组:"+ Arrays.toString(array));
        List<String> list = Arrays.asList(array);
        System.out.println("集合:"+list);
        //对该集合的操作就是对原数组对应的操作,也就是改了集合数组也会跟着改
        list.set(1, "six");//将下标1的元素覆盖为six
        System.out.println("集合:"+list);
        System.out.println("数组:"+ Arrays.toString(array));
        /*
         * 由于数组是定长的,并且操作集合就会改动数组,所以当我们对集合进行增删时,
         * 就会导致对数组也进行同等操作,这时就会抛出异常
         * UnSupportedOperationException
         * UnSupported 不支持的
         * Operation 操作
         */
        //list.add("seven");
        System.out.println("集合:"+list);
        System.out.println("数组:"+ Arrays.toString(array));
        /*
         * 如果有增删的需求,就需要另外的创建一个集合,并先将数组转换的集合的内容导入到新集合中即可
         */
        //List<String> list2 = new ArrayList<>();
        //list2.addAll(list);
        /*
         * 所有的集合都支持一个参数为Collection的构造器,
         * 目标是在创建当前集合的同时,将参数集合的所有元素也包含进去
         */
        List<String> list2 = new ArrayList<>(list);
        list2.add("seven");
        System.out.println(list2);
    }
}

集合的排序

SortListDemo
package Part06Collection;

import java.util.*;

/**
 * 集合的排序
 * 集合的工具类java.util.Collections提供了一个静态方法sort,
 * 可以对List集合进行自然排序
 */
public class SortListDemo {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            //每次向集合中添加一个100以内的随机整数
            list.add(random.nextInt(100));
        }
        System.out.println(list);
        Collections.sort(list);//自然排序,从小到大
        System.out.println(list);
    }
}
SortListDemo2
package Part06Collection;

import java.util.*;

/**
 * 排序自定义类型元素
 */
public class SortListDemo2 {
    public static void main(String[] args) {
        List<Point> list = new ArrayList<>();
        list.add(new Point(1, 2));
        list.add(new Point(15, 66));
        list.add(new Point(3, 4));
        list.add(new Point(9, 0));
        list.add(new Point(7, 8));
        System.out.println(list);
        /*
         *  sort方法对排序的集合有要求:要求集合元素必须实现了Comparable接口.
         *  实现了该接口的类,并且重写一个方法compareTo方法用于定义比较大小的规则,
         * 从而进行元素间的比较,进行排序否则编译就不通过
         */
        //Collections.sort(list);
        //使用匿名内部类的形式创建一个比较器,可以使用泛型约束我们比较的是两个Point
        Comparator<Point> com = new Comparator<Point>() {
            /*
             * 实现比较器之后,必须要重写方法compare,
             * 该方法用来定义参数o1和参数o2的比较大小规则,
             * 返回值用来表示o1和o2的大小关系
             */
            @Override
            public int compare(Point o1, Point o2) {
                //点与点比较一般都是距离原点的距离越远,就越大
                int len1 = o1.getX()*o1.getX() + o1.getY()*o1.getY();
                int len2 = o2.getX()*o2.getX() + o2.getY()*o2.getY();
                return len1-len2;
            }
        };
        Collections.sort(list,com);
        System.out.println(list);
    }
}

Map接口

概述

Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的键(key)另外一组值用于保存Map里的值(value),键和值是一一对应的关系,称为映射。根据键就能找到对应的值,类似于生活中一张身份证对应一个人一样。

Map的key和value可以是任何引用类型的数据,其中key不允许重复,同一个Map对象的任何两个key通过equals方法比较总是返回false。

特点

\1) Map集合中每个元素都有两个值, 分别是key(键) 和 value(值)

\2) Map集合中的key(键)不允许重复, 在第二次添加已有的key时, value会被会覆盖

\3) Map集合中的元素是无序的(即元素存入集合的顺序和取出时的顺序很可能不一致)

\4) Map集合中的key和value具有映射关系, 可以通过key(键)来获取对应的value(值)

key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的、确定的value。从Map中取出数据时,只要给出指定的key,就可以取出对应的value。

如果把Map里的所有key放在一起来看,它们就组成了一个Set集合(所有的key没有顺序,key与key之间不能重复),实际上Map确实包含了一个keySet()方法,用于返回Map里所有key组成的Set集合。

如果把Map里的所有value放在一起来看,它们又非常类似于一个List:元素与元素之间可以重复,每个元素可以根据索引来查找,只是Map中的索引(也就是key)不是从0开始的整数值,而是任意类型的对象;

如果需要从List集合中取出元素,则需要提供该元素的数字索引;如果需要从Map中取出元素,则需要提供该元素的key。因此,Map有时也被称为字典,或关联数组。

继承结构

Map接口

|— HashMap类

|— TreeMap类

|— Hashtable类

解释说明:

- Map集合是采用键-值对(key-value)的存储方式, 键(key)、值(value)可以是引用类型的数据, key不允许重复, vaue可以重复, key和value是一对一的关系, 通过指定的key总能找到唯一的、确定的value值

- HashMap 和 Hashtable 都是Map接口的实现类,它们之间的关系完全类似于ArrayList和Vector的关系

\1) HashMap是线程不安全的, 所以HashMap的性能要比HashTable高一些

\2) HashMap可以使用null作为key或value, Hashtable不允许使用null作为key和value;

\3) Hashtable是一个古老的Map实现类,JDK 1.0出现,出现时,Java还没有提供Map接口,命名没有遵守Java的命名规范,与Vector类似的是,尽量少用Hashtable实现类,即使需要创建线程安全的Map实现类,也无须使用Hashtable实现类,可以通过别的方式来解决线程安全问题。

- TreeMap是Map的子接口SortedMap的的实现类, 是可以支持对内部元素进行排序的类, 也正因为如此, TreeMap的执行效率通常要比HashMap和HashTable慢。

MapDemo

package Part06Collection;

import java.util.HashMap;
import java.util.Map;

/**
 * java.util.Map接口 查找表
 * Map体现的结构就是一个多行两列的表格,其中左列称为"key",右列称为"value"
 * Map总是以key-value的形式保存一组数组.并且可以根据key获取对应的value
 * Map有一个要求,key不允许重复(equals比较)
 *
 * 常用Map的实现类:
 * java.util.HashMap,我们称之为"散列表",当今查询速度最快的数据结构
 */
public class MapDemo {
    public static void main(String[] args) {
        //Map声明时,可以指定泛型,不过需要指定两个类型,一个是key的类型,一个value的类型
        Map<String,Integer> map = new HashMap();
        /*
         * V put(K k,V v);
         * 向当前map中存储一组键值对
         */
        map.put("语文", 80);
        //map.put("数学", 70).intValue();
        /*
         * 如果Map的value是包装类型,获取时,不要使用基本类型接收,
         * 避免自动拆箱时,引发空指针
         */
        Integer value = map.put("数学", 70);
        System.out.println("value:"+value);//如果key不存在,就返回null
        map.put("英文", 34);
        map.put("化学", 60);
        //{英文=34, 数学=70, 化学=60, 语文=80}
        System.out.println(map);
        //map在put时,如果key不存在,就直接存储,如果key存在,就会覆盖
        value = map.put("数学", 150);
        System.out.println("value:"+value);//如果key存在,返回被替换掉的元素
        System.out.println(map);
        /*
         * V get(Object k)
         * 根据给定的key获取对应的value,如果给定的key不存在,返回为null
         */
        Integer score = map.get("语文");
        System.out.println("语文成绩:"+score);
        score = map.get("体育");
        System.out.println("体育成绩:"+score);
        //返回map中的元素个数
        int size = map.size();
        System.out.println("集合中有"+size+"个元素");
        /*
         * 删除给定的key对应的这组键值对,返回值为这个key对应的value
         */
        score = map.remove("数学");
        System.out.println("删除了数学成绩:"+score);
        size = map.size();
        System.out.println("集合中有"+size+"个元素");
        //可以分别判断Map中是否包含给定的key或者value
        boolean ck = map.containsKey("英文");
        System.out.println("是否包含key:"+ck);
        boolean cv = map.containsValue(100);
        System.out.println("是否包含value:"+cv);
    }
}

MapDemo2

package Part06Collection;

import java.util.*;

/**
 * Map的遍历
 * Map支持三种遍历方式:
 * 1:单独遍历key
 * 2:遍历每一组键值对
 * 3:单独遍历value(这个操作不常用)
 */
public class MapDemo2 {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<>();
        map.put("语文", 98);
        map.put("数学", 100);
        map.put("英语", 80);
        map.put("物理", 60);
        map.put("java", 150);
        System.out.println(map);
        /*
         *  Set keySet()
         *  将当前的map中所有的key以一个Set集合的形式返回
         */
        Set<String> keySet = map.keySet();
        for (String s : keySet) {
            System.out.println("map的key是:"+s);
            System.out.println("map的value是:"+map.get(s));
        }
        /*
         * Collection values()
         * 将所有的value以一个集合的形式返回
         */
        Collection<Integer> values = map.values();
        for (Integer value : values) {
            System.out.println("map的value是:"+value);
        }
        /*
         * 遍历每一组键值对
         * Set entrySet()
         * 将当前Map中的每一组键值对以Entry对象实例形式来表示,存入集合中并返回,
         */
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        for (Map.Entry<String, Integer> entry : entrySet) {
            //从entry对象中获取key值
            String key = entry.getKey();
            //从entry对象中获取value值
            Integer value = entry.getValue();
            System.out.println("key:"+key+"===="+"value:"+value);
        }
        /*
         * JDK1.8之后,集合和Map都支持了基于lambda表达式形式的遍历
         */
        map.forEach(
                //此处k和v起什么名字无所谓,第一个值是key,第二个值是value
                (k,v)-> System.out.println(k+":"+v)
        );
        Collection<String> c = new ArrayList<>();
        c.add("one");
        c.add("two");
        c.add("three");
        c.add("four");
        c.add("five");
        c.forEach(
                (e)-> System.out.println(e)
        );
        //如果参数只有一个,小括号可以省略
        c.forEach(
                e-> System.out.println(e)
        );
        //如果输出的参数和传入的参数都是一个,参数也可以省略,并且替换为::
        c.forEach(
                System.out::println
        );
    }
}

代码分析

Demo1

package Part06Collection;

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

/**
 * 局部变量存在栈中
 * 对象在堆里
 * 属性在对象中(在堆里)
 *
 * 基本类型保存的值就是值本身
 * 引用类型保存的值是对象在堆中的地址
 */
public class Demo {
    public static void main(String[] args) {
        String s = "hello";
        int a = 1;
        Point p = new Point(1, 2);
        Collection c = new ArrayList();
        c.add(p);
        test(s, a, p, c);
        System.out.println("s:"+s);
        System.out.println("a:"+a);
        System.out.println("p:"+p);
        System.out.println("c:"+c);
    }
    public static void test(String s,int a,Point p,Collection c){
        a++;
        s= s + "world";
        p.setX(3);
        p = new Point(4, 5);
        c.clear();
        c.add(p);
        c = new ArrayList();
        p.setX(7);
        c.add(p);
    }
}
  • 执行test方法最后一行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2Erqsksa-1654135210713)(pic/image-20220523202224814.png)]

  • 执行完test方法,清空test方法的局部变量和引用

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EdrAJqlP-1654135210714)(pic/image-20220523202200438.png)]

  • 清理堆中无引用对象

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BXCcDpZd-1654135210715)(pic/image-20220523202126267.png)]

Demo2

package Part06Collection;

import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

/**
 * 局部变量存在栈中
 * 对象在堆里
 * 属性在对象中(在堆里)
 *
 * 基本类型保存的值就是值本身
 * 引用类型保存的值是对象在堆中的地址
 */
public class Demo2 {
    public static void main(String[] args) {
        int a = 1;
        String str = "hello";
        Point p = new Point(1,2);
        String[] arr = {"one","two","three",str};
        int[] arr1 = {1,2,3,4,a};
        Point[] arr2 = {new Point(1,2),new Point(3,4),new Point(5,6),p};
        dosome(a,str,p,arr,arr1,arr2);
        System.out.println("a:"+a);
        System.out.println("str:"+str);
        System.out.println("p:"+p);
        System.out.println("arr:"+ Arrays.toString(arr));
        System.out.println("arr1:"+Arrays.toString(arr1));
        System.out.println("arr2:"+Arrays.toString(arr2));
    }
    public static void dosome(int a,String str,Point p,String[] arr,int[] arr1,Point[] arr2) {
        arr1[a] = 3;
        arr[a] = "str";
        arr[a+1] = str;
        str = "world";
        str = arr[2];
        str+="!!";
        p.setX(4);
        p = arr2[2];
        p.setX(6);
        arr2 = Arrays.copyOf(arr2, arr2.length-1);
        arr2[2].setX(8);
        arr2 = new Point[]{new Point(2,2),p};
        arr2[arr2.length-1].setX(12);
    }
}
  • 执行dosome方法之前

在这里插入图片描述

  • 执行dosome方法进行传参时

在这里插入图片描述

  • dosome方法执行完毕

在这里插入图片描述

  • dosome方法执行后,弹出相关局部变量,清除多余引用以及无引用对象

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值