JAVA集合专题1 —— 引入

引言

之前我们使用数组保存多个数据,但是,数组有一些不足的地方:

  • 数组长度开始时必须指定,而且一旦指定,不能更改
int[] a = new int[3];
  • 保存的必须为同一类型的元素
  • 使用数组进行增加元素比较麻烦

与之对应的,集合就没有这些缺点,集合相比于数组,有以下优点:

  • 可以动态保存任意多个对象
  • 提供了一系列方便的操作对象的方法: add(增)、remove(删)、set(改)、get(查)等
  • 使用集合添加,删除新元素十分简洁

集合体系

虚线实现接口,实线继承类

单列集合

在这里插入图片描述

双列集合

在这里插入图片描述

代码演示
package cs.kaoyan.javase.com;

import java.util.ArrayList;
import java.util.HashMap;

public class Test {
    //添加注解,抑制警告
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        //单列集合演示:添加元素的时候是单列的
        ArrayList arrayList = new ArrayList();
        arrayList.add("java");
        arrayList.add("se");
        arrayList.add("easy");

        //双列集合演示:添加元素的时候是双列的
        HashMap hashMap = new HashMap();
        hashMap.put("no1","java");
        hashMap.put("no2","c++");
        hashMap.put("no3","python");
    }
}

Collection接口和常用方法

Collection接口实现类的特点:

public interface Collection<E> extends Iterable<E>
  • collection实现子类可以存放多个元素,每个元素可以是Object
  • Collection的实现类,可以存放重复的元素,有些不可以
  • Collection的实现类,有些是有序的(比如List),有些不是有序(比如Set)
  • Collection接口没有直接的实现子类,是通过它的子接口Set 和List来实现的
代码演示
package cs.kaoyan.javase.com;

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

public class Test {
    //添加注解,抑制警告
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        //字符串
        list.add("java");
        //整型
        list.add(10);
        //boolean
        list.add(true);
        //[java, 10, true]
        System.out.println(list);

        //查找元素是否存在
        //存在则返回true
        System.out.println(list.contains("java"));

        //删除下标所在的元素
        list.remove(0);
        //删除指定元素
        list.remove(true);
        //[10]
        System.out.println(list);

        //获取集合中元素的个数
        //1
        System.out.println(list.size());

        //判断集合是否非空
        //false
        System.out.println(list.isEmpty());

        //清空集合
        list.clear();
        //0
        System.out.println(list.size());

        //创建一个新集合arrayList
        ArrayList arrayList = new ArrayList();
        arrayList.add("迪迦奥特曼");
        arrayList.add(100);

        //向集合list中添加多个元素
        list.addAll(arrayList);
        //[迪迦奥特曼, 100]
        System.out.println(list);

        list.add("acm-icpc");
        //删除多个元素
        list.removeAll(arrayList);
        //[acm-icpc]
        System.out.println(list);
    }
}

使用迭代器遍历集合元素

  • lterator对象称为迭代器,主要用于遍历Collection集合中的元素
  • 仅用于遍历集合,lterator本身并不存放对象
  • 需要注意的是:在调用next方法之前必须要调用hasNex进行检测。若不调用且下一条记录无效,直接调用next方法会抛出NoSuchElementException异常
package cs.kaoyan.javase.com;

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

public class Test {
    //添加注解,抑制警告
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        //父类引用指向子类对象(向上转型)
        Collection coll =  new ArrayList();

        coll.add(new Book("计算机网络","长风",18.0));
        coll.add(new Book("数据结构","咸鱼",28.0));
        coll.add(new Book("操作系统","天明",38.0));

        //先得到coll对应的迭代器
        Iterator iterator = coll.iterator();
        //使用while循环遍历
        //需要先判断是否还有数据
        while (iterator.hasNext()){
            //获取数据
            Object next = iterator.next();
            System.out.println(next);
        }

        /*Book{name='计算机网络', author='长风', price=18.0}
        Book{name='数据结构', author='咸鱼', price=28.0}
        Book{name='操作系统', author='天明', price=38.0}*/

    }
}

class Book{
    private String name;
    private String author;
    private double price;

    //构造器
    public Book(String name, String author, double price) {
        this.name = name;
        this.author = author;
        this.price = price;
    }

    //重写toString
    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                '}';
    }
}

模拟List,建立自己的"List",并用快慢指针取这个链表的倒数第x个结点

  • 要求1:模拟List,建立自己的"List",然后实现对链表元素的增删改查

  • 要求2:实现一个方法,接收一个链表的头结点和int类型值x,取这个链表的倒数第x个结点内容

  • 第一步:先模拟链表的建立

package cs.kaoyan.javase.com;

//抑制所有警告
@SuppressWarnings({"all"})
public class MyLinkList {
    private Node head;//单链表的头结点
    private int size;//记录链表存储了多少数据

    /**
     * 单链表的添加方法
     * @param value:要添加的值
     * @return:添加是否成功
     */
    public boolean add(String value){
        //不允许插入null
        if (value == null){
            return false;
        }
        //将新元素添加到头结点后面
        //判断链表是否为空
        if (isEmpty()) {
            //链表为空(head -> null),新建一个结点,插入表头
            Node node = new Node(value);
            //不带头结点的单链表
            head = node;
            //以上两行代码可以简写为 : head = new Node(value);
            //插入新结点之后链表长度加1
            size++;
            //插入成功
            return true;
        }

        //代码执行到这里说明链表不为空,此时默认在表尾插入
        //要在表为插入数据,需要先找到表尾元素

        //在对链表的操作中,除非特殊要求需要操作头指针,其余情况不要对头指针进行操作
        //否则容易造成GC回收资源,从而引发错误

        //temp做为临时指针
        Node temp = head;
        //使用while循环找到链表的最后一个元素
        while (temp.next != null){
            //只要下一个元素不为null,就可以后移指针
            temp = temp.next;
        }

        //代码执行到这里,说明已经到达了链表末尾
        //此时可以新建结点,然后接入链表
        Node node = new Node(value);
        temp.next = node;
        //以上两行代码可以简写为 : temp.next = new Node(value);
        size++;
        return true;
    }

    /**
     * 单链表的删除方法
     * @param value:删除的值
     * @return:表示删除是否成功
     */
    public boolean remove(String value){
        //不允许删除null
        if (value == null) {
            return false;
        }
        //先判断链表是否为空
        if (isEmpty()){
            //链表为空,无法删除
            return false;
        }

        //代码执行到这里,表示链表非空,此时定义一个临时指针用来遍历链表
        //找到需要删除的元素时,即可删除

        //一般不操作链表的头指针,故创建一个临时变量,用于从头遍历链表
        Node temp = head;

        //删除头结点
        if (temp.value.equals(value)){
            head = head.next;
            size--;
        }

        //找到待删除结点的前一个结点,修改指针即可
        while (temp.next != null && !temp.next.value.equals(value)){
            //指针后移
            temp = temp.next;
        }

        //如果指针移动到链表最后,说明待删除元素不存在,返回false
        if (temp.next == null){
            return false;
        }
        //执行完while循环,temp指针指向待删除结点的前一个结点
        //且此时temp指向的结点不是最后一个结点
        //这时移动指针来实现元素删除
        temp.next = temp.next.next;
        size--;
        return true;
    }


    /**
     * 单链表的查找方法
     * @param value:待查找的值
     * @return:待查找的元素是否存在
     */
    public boolean contains(String value){
        //链表为空,返回false
        if (isEmpty()){
            return false;
        }

        //查找null元素,返回false
        if (value == null){
            return false;
        }

        //遍历链表
        Node temp = head;
        //如果下一个结点不为null
        //且当前结点的值不等于要查找的元素值,就可以后移指针
        while (temp.next != null && !temp.value.equals(value)){
            temp = temp.next;
        }
        //while循环结束后,temp要么指向最后一个结点,要么已经查找到元素

        //指针指向链表最后一个结点,此时temp.next == null
        if (!temp.value.equals(value)){
            //未查找到指定元素
            return false;
        }
        //代码执行到这里,说明找到了要查找的元素
        return true;
    }

    /**
     *
     * @param oldValue:要被替换掉的老元素
     * @param newValue:用来替换的新元素
     * @return
     */
    public boolean set(String oldValue,String newValue){
        //如果链表为空,那么返回false
        if (isEmpty()){
            return false;
        }

        //设置临时指针
        Node temp = head;
        while (!temp.value.equals(oldValue) && temp != null){
            temp = temp.next;
        }

        if (temp == null){
            //遍历完链表,没找到oldValue
            return false;
        }

        //找到需要修改的元素
        temp.value = newValue;
        return true;

    }

    public boolean isEmpty(){
        //链表的size为0表示链表为空 -> 返回true
        return size == 0;
    }

    //返回链表中倒数第k个结点
    /***
     * 解题思路:
     * 快慢指针,先让快指针走k步,然后两个指针同时走,当快指针到头时,慢指针就是链表倒数第k个节点
     * 快慢指针思想的优势:使用双指针可以不用统计链表长度
     */
    public Node getKElement(Node head, int k){
        if (k < 0 || head == null){
            return null;
        }

        //初始化:快慢指针都指向头节点head
        //设置快指针
        Node fast = head;
        //设置慢指针
        Node low = head;

        //快指针先往前走k步
        while (k > 0 && fast != null){
            fast = fast.next;
            k--;
        }

        //快慢指针一起走
        while (fast != null){
            fast = fast.next;
            low = low.next;
        }

        //最后输出慢指针指向的元素即可
        System.out.println(low.value);

        return low;
    }

    //getter方法,获取链表的头结点
    public Node getHead() {
        return head;
    }

    //单链表的结点
    //内部类:外部无法new对象
    class Node{
        String value;//值域
        Node next;//指针域

        //单参构造器
        public Node(String value) {
            this.value = value;
        }

        //双参构造器
        public Node(String value, Node next) {
            this.value = value;
            this.next = next;
        }



        @Override
        public String toString() {
            return "Node{" +
                    "value='" + value + '\'' +
                    ", next=" + next +
                    '}';
        }
    }
}

  • 写测试类
package cs.kaoyan.javase.com;

public class Test {
    public static void main(String[] args) {
        //创建链表对象
        MyLinkList myLinkList = new MyLinkList();

        //增 1 -> 2 -> 3 -> 4
        myLinkList.add("1");
        myLinkList.add("2");
        myLinkList.add("3");
        myLinkList.add("4");

        System.out.println(myLinkList.contains("0"));//false
        System.out.println(myLinkList.contains("2"));//true
        System.out.println(myLinkList.contains("3"));//true
        System.out.println(myLinkList.contains("4"));//true
        System.out.println(myLinkList.contains("1"));//true
        System.out.println(myLinkList.contains("8"));//false
        System.out.println(myLinkList.contains("9"));//false

        //删 1 -> 2 -> 3 -> 4 —— 2
        myLinkList.remove("1");
        myLinkList.remove("3");
        myLinkList.remove("4");

        //改 2 —— 8
        myLinkList.set("2","8");


        //增 8 -> 6 -> 7 -> 1 -> 9
        myLinkList.add("6");
        myLinkList.add("7");
        myLinkList.add("1");
        myLinkList.add("9");

        //调用getter方法,获取链表的头结点
        MyLinkList.Node head = myLinkList.getHead();
        myLinkList.getKElement(head,2);

        System.out.println(myLinkList);
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值