前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java基础差缺补漏系列之集合系列2

Java基础差缺补漏系列之集合系列2

作者头像
冷环渊
发布2021-10-19 15:29:17
2660
发布2021-10-19 15:29:17
举报

java

每日格言

明道德以固本,重修养以安魂,知廉耻以净心,去贪欲以守节。

linkedlist

底层为链表 LinkedList 常用方法:

  • 增加:addFirst(E e),addLast(E e),offer(E e),offerFirst(E e),offerLast(E e)
  • 删除:poll(),pollFirst(),pollLast(),removeFirst(),removeLast()
  • 修改:set(int index, E element)
  • 查看:element(),getFirst(),getLast(),indexOf(Object o),lastIndexOf(Object o),peek(),peekFirst(),peekLast()
  • 判断:

示例代码:

代码语言:javascript
复制
//    现有一个linkedlist集合对象
        public static void main(String[] args) {
            LinkedList list = new LinkedList();
//          能否重复添加数据
            list.add("aaaa");
            list.add("bbbb");
            list.add("aaaa");
            list.add("cccc");
            System.out.println(list);
//            收尾添加
            list.addFirst("ffff");
            list.addLast("zzzz");
            System.out.println(list);
//            添加元素到尾端
            list.offer("ll");
            System.out.println(list);

            list.offerFirst("pp");
            list.offerLast("rr");
//            删除首个元素
            System.out.println(list);
            System.out.println("删除"+list.poll());//删除头上的元素,并且返回删除的元素
            System.out.println("删除"+list.pollFirst());
            System.out.println("删除"+list.pollLast());
            System.out.println(list);
//查找头尾元素
            System.out.println(list.peek());
            System.out.println(list.peekLast());
//            list.clear();

//           方法的举例
            System.out.println(list);
            System.out.println(list.pollLast());//如果没有返回null,不影响程序执行
            System.out.println(list.removeFirst());//Exception in thread "main" java.util.NoSuchElementException,会报错,

//            遍历
            System.out.println("----------");
//            1
            for (int i=0; i

为什么有功能相同的方法:以

pollFirst(),pollLast(),

removeFirst(),removeLast()

为例:

removeFirst是早版本的

pollFirst是jdk1.6版本的

实测区别:

代码语言:javascript
复制
//           方法的举例
            System.out.println(list);
            System.out.println(list.pollLast());//如果没有返回null,不影响程序执行
            System.out.println(list.removeFirst());//Exception in thread "main" java.util.NoSuchElementException,会报错,

同样是空的集合,pollFirst删除第一个如果没有返回null,无报错,removeFirst会报错没有数据

相比之下1.6之后的方法提高了健壮性,其他类似方法与这一对一致,

遍历方式:

源码看到,这个迭代器相对好,内存上的节省,例子:

代码语言:javascript
复制
for ( Iterator it1 = list.iterator();it1.hasNext();){
                System.out.println(it1.next());
            }

linkedlist的原理

对比学习:

Arraylist数据结构:

Linledlist数据结构:

物理结构:紧密结构

物理结构:跳转结构

逻辑结构:线性表(数组)

逻辑结构:线性表(链表)

Linkedlist是双向链表:

简要底层原理图:

模拟一个linkedList

首先是我们的节点类

代码语言:javascript
复制
package linkedListPrc;

import javax.xml.soap.Node;

public class Test02 {//节点类
//    三个属性
//    上一个元素的地址
private Test02 pre;
//    当前存放的元素
private Object obj;
//    下一个元素的地址
private Test02 next;

    public Test02 getPre() {
        return pre;
    }

    public void setPre(Test02 pre) {
        this.pre = pre;
    }

    public Object getObj() {
        return obj;
    }

    public void setObj(Object obj) {
        this.obj = obj;
    }

    public Test02 getNext() {
        return next;
    }

    public void setNext(Test02 next) {
        this.next = next;
    }

    public Test02() {
    }
}

之后就是我们的mylist源码

代码语言:javascript
复制
public class MyLinkedList {
//   链中一个定有一个首节点
Test02 first;
//    链中一个有一个尾节点
Test02 last;
//    计数器
    int count =0;
//    提供一个构造器
    public  MyLinkedList(){

    }
//    元素添加方法
    public void add(Object o){
        if (first ==null){//证明添加的元素是第一个
//            那接下来我们需要吧添加的元素封装成一个node
            Test02 n = new Test02();
            n.setPre(null);
            n.setObj(o);
            n.setNext(null);
            first = n;
            last = n;
        }else {//证明以及不是链中的第一个节点了
//            先把添加的元素封装成一个node对象
            Test02 n = new Test02();
            n.setPre(last);
            n.setObj(o);
//            当前链中的最后一个节点的下一个元素要指向n
            last.setNext(n);
//            将最后一个节点变成n
            last = n;
        }
        count++;
    }
    public int getSize(){
        return count;
    }
//    通过下标得到元素
    public  Object getelByindex(int index){
        if (index>count){
            System.out.println("这个索引上没有数据,检查插入的元素是否达到查找索引的数量");
        }
//        获取链表的头元素
        Test02 n = first;
        for (int i = 0;i< index;i++){
//          一路next找到想要的元素
                n = n.getNext();
        }
          return n.getObj();
    }
}

linkdelist部分源码解读

代码语言:javascript
复制
public class LinkedList{
     //长度
   transient int size = 0;

     //首位
    transient Node first;

     //尾位
    transient Node last;
    
     //封装节点对象方法
        private static class Node {
        E item;
        Node next;
        Node prev;

        Node(Node prev, E element, Node next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }
    
     //首元素
        transient Node first;
     //尾元素
        transient Node last;

	 //空构造器
            public LinkedList() 	{
    }
    //添加元素操作
    public boolean addAll(Collection c) {
        return addAll(size, c);
    }
   
      void linkLast(E e) { //添加的元素e
        final Node l = last;
           //将链表中的last节点给l,如果是第一个元素的话l为null
        final Node newNode = new Node<>(l, e, null);
          //将元素封装为一个node的具体对象
        last = newNode;
           //将链表的为节点指向新创建的对象
        if (l == null)如果添加的是第一个节点
            first = newNode;//将链表的first节点只想为新节点
        else //如果添加的不是第一个节点
            l.next = newNode;//将l的下一个指向新的节点
        size++; //集合中元素数量加1
        modCount++;
    }
    
    //查找方法
        public E get(int index) {
        checkElementIndex(index);
        return node(index).item;
    }
    
    //二分查找的方式遍历链表
        Node node(int index) {

        if (index < (size >> 1)) {
            Node x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
        } else {
            Node x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }
    
}

迭代器

迭代器的源码,以及两个经典方法

面试题:迭代器对应的关系

hashnext与next方法的具体实现
增强for循环起始底层也是用迭代器完成的

用debug查看增强for循环,会发现,执行的下一步还是会进到iterator里

listirerator

加入字符串,比如我们想想要在代码中遍历到cc后新增一个kk

代码语言:javascript
复制
       List list = new ArrayList();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        list.add("dd");
        list.add("ee");

        Iterator iterator = list.iterator();
        while (iterator.hasNext()){

            if ("cc".equals(iterator.next())){
                list.add("kk");
            }

        }

控制台发生并发修改异常

出错原因:

迭代器和lsit同时操作集合,

如何解决:事情让一个迭代器做,新迭代器:listiterator,迭代和添加操作都用listiterator来操作

代码语言:javascript
复制
        ListIterator iterator = list.listIterator();
        while (iterator.hasNext()){

            if ("cc".equals(iterator.next())){
                iterator.add("kk");
            }

        }

我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=3btqwmdvn4cgo

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-08-20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • java
    • 每日格言
      • linkedlist
        • linkedlist的原理
        • 模拟一个linkedList
        • linkdelist部分源码解读
      • 迭代器
        • listirerator
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档