集合-LinkedList

LinkedList

LinkedList的概述

LinkedList的底层使用双向链表实现。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YFvfuWIM-1681288911283)(E:\Java笔记\javaSE\集合(容器)(9)\集合\LinkedList.assets\image-20230406115511053.png)]

链表是一种线性数据结构,其中每个元素都是一个单独的对象,包含一个指向列表中下一个节点的引用。

它可以用于实现各种抽象数据类型,例如列表、堆栈、队列等。

LinkedList的优缺点

优点

  • 插入和删除操作的时间复杂度为O(1),相比于数组的O(n)更加高效。
  • 链表的大小可以动态调整,不像数组需要预先分配空间。
  • 链表的节点可以在内存中部连续存储,因此可以更加的灵活的利用内存空间。

缺点

  • 访问元素的时间复杂度为O(n),相比于数组的O(1)较低效。
  • 链表需要额外的空间来存储指向下一个节点的指针,因此占用的空间比数组更大。
  • 链表的随机访问效率比较低,因为需要从头开始遍历链表才能找到指定位置的节点。

LinkedList的创建方式

LinkedList linkedList = new LinkedList();
//向上转型
List linkedLists = new LinkedList();

常用方法,以及源码分析

方法返回类型解释
add(E e)boolean将指定元素添加到此列表的结尾
add(int index, E element)void将此列表中指定的位置插入指定的元素
addFirst(E e)void将指定元素插入此列表的开头
addLast(E e)void将指定元素添加到此列表的结尾
clear()void从此列表中移除所有元素
get(int index)E返回此列表中指定位置处的元素
getFirst()E返回此列表的第一个元素
remove()E获取并移除此列表的头(第一个元素)
remove(int index)E移除此列表中指定位置的元素
removeFirst()E移除并返回此列表的第一个元素
removelast()E移除并返回此列表的最后一个元素
set(int index,E element)E将此列表中指定位置的元素替换为指定的元素
size()int返回此列表的元素数

add(E e)

源码分析:

通过调用 linkLast(E e) 方法将元素添加到链表的末尾。

linkLast(E e) 方法创建一个新的节点,并将其插入到链表的末尾。如果链表为空,则将新节点设置为第一个节点。否则,将新节点链接到最后一个节点。最后,更新链表的大小和 modCount 变量。

	public boolean add(E e) {
        //调用linklast方法将元素添加到链表的尾端
    	linkLast(e);
        //添加成功,返回true
    	return true;
	}
	void linkLast(E e) {
        //获取链表的最后一个节点
        final Node<E> l = last;
        //创建最后一个节点,他的前驱节点是l,后去节点为null,数据为e
        final Node<E> newNode = new Node<>(l, e, null);
        //将链表的尾节点指向新节点
        last = newNode;
        //判断节点是否为null
        if (l == null)
            //为null则将节点指向新节点
            first = newNode;
        else
            //如果不为null,将原尾节点的后继节点指向新节点
            l.next = newNode;
        //聊表的大小加1
        size++;
        //修改计数器
        modCount++;
    }

案例:

public static void main(String[] args) {
        LinkedList linkedList = new LinkedList();
    	//添加数据
        linkedList.add("张三");
        linkedList.add("李四");
    	//输出此列表
        System.out.println(linkedList);
    }

add(int index, E element)

源码分析:

将元素添加到指定位置

public void add(int index, E element) {
   		 //检查索引是否越界
        checkPositionIndex(index);
		//索引与长度相等
        if (index == size)
            //在链表尾部添加数据
            linkLast(element);
        else
            //在指定位置之前添数据
            linkBefore(element, node(index));
    }

    private void checkPositionIndex(int index) {
        //判断索引是否合法
        if (!isPositionIndex(index))
            //不合法则抛出下标越界异常
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    void linkLast(E e) {
        //获取链表的最后一个节点
        final Node<E> l = last;
        //创建一个新的节点,他的前驱节点是l,后去节点为null,数据为e
        final Node<E> newNode = new Node<>(l, e, null);
        //将链表的最后一个节点指向新节点
        last = newNode;
        //判断链表是否为null
        if (l == null)
            //将第一个节点指向新节点
            first = newNode;
        //如果不为null
        else
            //将最后一个节点的下一个节点指向新节点
            l.next = newNode;
        //链表大小加1
        size++;
        //修改计数器加1
        modCount++;
    }
    void linkBefore(E e, Node<E> succ) {
        //获取指定位置的前一个节点
        final Node<E> pred = succ.prev;
        //创建一个新节点
        final Node<E> newNode = new Node<>(pred, e, succ);
        //将指定位置的前一个节点的下一个节点指向新节点
        succ.prev = newNode;
        //如果指定位置的前一个节点为null,
        if (pred == null)
            //将第一个节点指向新节点
            first = newNode;
        //如果指定位置的前一个节点不为null
        else
            //将前一个节点的下一个节点指向新节点
            pred.next = newNode;
        //链表大小加1
        size++;
        //修改计数器加1
        modCount++;
    }

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    System.out.println(linkedList);
    //位置1,添加数据
    linkedList.add(1,"王五");
    System.out.println(linkedList);
}

addFirst(E e)

源码分析:

将指定元素插入到此列表的开头

public void addFirst(E e) {
    // 在链表的头部添加一个新节点
    linkFirst(e);
}
private void linkFirst(E e) {
    // 获取头节点
	final Node> f = first;
	// 创建一个新节点,它的前驱节点为null,数据为e,后继节点为头节点f
	final Node> newNode = new Node<>(null, e, f);
	// 将头节点指向新节点
	first = newNode;
	// 如果头节点为null,说明
	if (f == null)
        //链表为空,将尾节点指向新节点
		last = newNode;
	// 否则将头节点的前驱节点指向新节点
	else
		f.prev = newNode;
	// 链表长度加1
	size++;
	// 修改次数加1
	modCount++;
  }

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    System.out.println(linkedList);

    linkedList.add(1,"王五");
    System.out.println(linkedList);
	//列表开头添加数据
    linkedList.addFirst("赵六");
    System.out.println(linkedList);

}

addLast(E e)

源码分析:

将指定元素添加到此列表的结尾

 public void addLast(E e) {
     //在链表的尾部添加一个新节点
        linkLast(e);
    }
void linkLast(E e) {
        //获取链表的最后一个节点
        final Node<E> l = last;
        //创建一个新的节点,他的前驱节点是l,后去节点为null,数据为e
        final Node<E> newNode = new Node<>(l, e, null);
        //将链表的最后一个节点指向新节点
        last = newNode;
        //判断链表是否为null
        if (l == null)
            //将第一个节点指向新节点
            first = newNode;
        //如果不为null
        else
            //将最后一个节点的下一个节点指向新节点
            l.next = newNode;
        //链表大小加1
        size++;
        //修改计数器加1
        modCount++;
    }

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    System.out.println(linkedList);

    linkedList.add(1,"王五");
    System.out.println(linkedList);

    linkedList.addFirst("赵六");
    System.out.println(linkedList);
	//列表结尾添加数据
    linkedList.addLast("唐七");
    System.out.println(linkedList);
}

clear():

源码分析:

从此列表中移除所有元素

public void clear() {
    // 遍历链表中的每一个节点
    for (Node<E> x = first; x != null; ) {
        // 保存当前节点的下一个节点
        Node<E> next = x.next;
        // 将当前节点的数据项置为null
        x.item = null;
        // 将当前节点的前驱和后继节点都置为null
        x.next = null;
        x.prev = null;
        // 将当前节点指向下一个节点
        x = next;
    }
    // 将链表的头节点和尾节点都置为null
    first = last = null;
    // 将链表的大小置为0
    size = 0;
    // 修改计数器
    modCount++;
}

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    
    linkedList.add("张三");
    linkedList.add("李四");
    linkedList.add(1,"王五");
    linkedList.addFirst("赵六");
    linkedList.addLast("唐七");
    System.out.println(linkedList);

    //清除此列表数据
    linkedList.clear();
    System.out.println(linkedList);;
}

get(int index)

源码分析:

返回此列表中指定位置处的元素

public E get(int index) {
    //校验索引是否合法
    checkElementIndex(index);
    //返回该索引对应的节点的数据
    return node(index).item;
}
private void checkPositionIndex(int index) {
        //判断索引是否合法
        if (!isPositionIndex(index))
            //不合法则抛出下标越界异常
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }
Node<E> node(int index) {
      // 如果要查找的节点在链表的前半部分
        if (index < (size >> 1)) {
            // 从头节点开始遍历
            Node<E> x = first;
            // 遍历到要查找的节点
            for (int i = 0; i < index; i++)
                // 指针指向下一个节点
                x = x.next;
            // 返回查找到的节点
            return x;
            // 如果要查找的节点在链表的后半部分
        } else {
            // 从尾节点开始遍历
            Node<E> x = last;
            // 遍历到要查找的节点
            for (int i = size - 1; i > index; i--)
                // 指针指向上一个节点	
                x = x.prev;
            // 返回查找到的节点
            return x;
        }
    }

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    linkedList.add(1,"王五");
    linkedList.addFirst("赵六");
    linkedList.addLast("唐七");
    System.out.println(linkedList);

    //获取指定位置的数据
    System.out.println(linkedList.get(2));
}

getFirst()

源码分析:

返回此列表的第一个元素

public E getFirst() {
    //获取链表的头节点
    final Node<E> f = first;
    //如果头节点为null
    if (f == null)
        //抛出NoSuchElementException异常
        throw new NoSuchElementException();
    //返回头节点的数据
    return f.item;
}

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    linkedList.add(1,"王五");
    linkedList.addFirst("赵六");      
    linkedList.addLast("唐七");
    System.out.println(linkedList);
    //获取此列表的第一个节点
    System.out.println(linkedList.getFirst());

}

remove()

源码分析:

获取并移除此里列表的头(第一个元素)

public E remove() {
    //调用移除第一个元素方法
    return removeFirst();
}
public E removeFirst() {
    // 获取链表的头节点
    final Node<E> f = first;
    // 如果头节点为空,
    if (f == null)
        //抛出NoSuchElementException异常
        throw new NoSuchElementException();
    // 返回调用调用unlinkFirst方法删除头节点并返回删除的元素
    return unlinkFirst(f);
}
 private E unlinkFirst(Node<E> f) {
    // assert f == first && f != null;
     // 获取头节点的元素
    final E element = f.item;
     // 获取头节点的下一个节点
    final Node<E> next = f.next;
     // 将头节点的元素置为空
    f.item = null;
     // 将头节点的下一个节点置为空,以便垃圾回收
    f.next = null; // help GC
     // 将链表的头节点指向原头节点的下一个节点
    first = next;
     // 如果原头节点的下一个节点为空
    if (next == null)
        //将链表的尾节点也置为空
        last = null;
    else
        // 否则将原头节点的下一个节点的前一个节点置为空
        next.prev = null;
     // 链表的大小减1
    size--;
     // 修改计数器加1
    modCount++;
     // 返回删除的元素
    return element; 
}

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    linkedList.add(1,"王五");
    linkedList.addFirst("赵六");
    linkedList.addLast("唐七");
    
    //获取并移除此列表的第一个节点
    System.out.println(linkedList.remove());
    //输出此列表的全部数据
    System.out.println(linkedList);
}

remove(int index)

源码分析:

移除指定列表中的指定位置的元素

//删除指定位置的节点
public E remove(int index) {
    // 检查索引是否越界
    checkElementIndex(index);
    // 删除并返回指定位置的节点
    return unlink(node(index));
}
// 检查索引是否越界
private void checkElementIndex(int index) {
    // 如果索引越界
    if (!isElementIndex(index))
        //则抛出IndexOutOfBoundsException异常
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
// 删除指定节点
E unlink(Node<E> x) {
    // 获取节点的值	
    final E element = x.item;
    // 获取下一个节点
    final Node<E> next = x.next;
    // 获取上一个节点
    final Node<E> prev = x.prev;

    // 如果上一个节点为空
    if (prev == null) {
        // 将下一个节点设为头节点
        first = next;
    } else {
	    // 将上一个节点的下一个节点设为当前节点的下一个节点
        prev.next = next;
        // 将当前节点的上一个节点设为空
        x.prev = null;
    }

    // 如果下一个节点为空
    if (next == null) {
        // 将上一个节点设为尾节点
        last = prev;
    } else {
        // 将下一个节点的上一个节点设为当前节点的上一个节点
        next.prev = prev;
        // 将当前节点的下一个节点设为空
        x.next = null;
    }
	
    // 将当前节点的值设为空
    x.item = null;
    // 链表大小减一
    size--;
    // 修改次数加一
    modCount++;
    // 返回删除的节点的值
    return element;
}

// 获取指定位置的节点
Node<E> node(int index) {
    
	// 如果索引小于链表大小的一半
    if (index < (size >> 1)) {
         // 从头节点开始遍历
        Node<E> x = first;
        for (int i = 0; i < index; i++)
            // 遍历到指定位置
            x = x.next;
        // 返回指定位置的节点
        return x;
   // 如果索引大于等于链表大小的一半
    } else {
        // 从尾节点开始遍历
        Node<E> x = last;
        for (int i = size - 1; i > index; i--)
            // 遍历到指定位置
            x = x.prev;
        // 返回指定位置的节点
        return x;
    }
}

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    linkedList.add(1,"王五");
    linkedList.addFirst("赵六");
    linkedList.addLast("唐七");

    //移除此列表的指定位置的节点
    System.out.println(linkedList.remove(1));
    //输出此列表的全部数据
    System.out.println(linkedList);
}

removeFirst()

源码分析:

移除并返回列表的第一个元素

// 删除链表的头节点
public E removeFirst() {
    // 获取头节点
    final Node<E> f = first;
    // 如果头节点为空,
    if (f == null)
        //抛出NoSuchElementException异常
        throw new NoSuchElementException();
    // 否则,调用unlinkFirst方法删除头节点
    return unlinkFirst(f);
}
 private E unlinkFirst(Node<E> f) {
    // assert f == first && f != null;
     // 获取头节点的元素
    final E element = f.item;
     // 获取头节点的下一个节点
    final Node<E> next = f.next;
     // 将头节点的元素置为空
    f.item = null;
     // 将头节点的下一个节点置为空,以便垃圾回收
    f.next = null; // help GC
     // 将链表的头节点指向原头节点的下一个节点
    first = next;
     // 如果原头节点的下一个节点为空
    if (next == null)
        //将链表的尾节点也置为空
        last = null;
    else
        // 否则将原头节点的下一个节点的前一个节点置为空
        next.prev = null;
     // 链表的大小减1
    size--;
     // 修改计数器加1
    modCount++;
     // 返回删除的元素
    return element; 
}

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    linkedList.add(1,"王五");
    linkedList.addFirst("赵六");
    linkedList.addLast("唐七");

    //移除并返回列表的第一个元素
    System.out.println(linkedList.removeFirst());
    //输出此列表的全部数据
    System.out.println(linkedList);
}

removelast()

源码分析:

移除并返回此列表最后一个元素

// 从链表的尾部删除一个节点
public E removeLast() {
    // 获取尾节点
    final Node<E> l = last;
    // 如果尾节点为空
    if (l == null)
        //抛出NoSuchElementException异常
        throw new NoSuchElementException();
    // 调用unlinkLast方法删除尾节点
    return unlinkLast(l);
}
// 删除链表中的一个节点
private E unlinkLast(Node<E> l) {
    // assert l == last && l != null;
    // 获取节点的数据
    final E element = l.item;
    // 获取节点的前一个节点
    final Node<E> prev = l.prev;
    // 将节点的数据置为空
    l.item = null;
    // 将节点的前一个节点置为空	
    l.prev = null; // help GC
    // 将尾节点指向前一个节点
    last = prev;
    // 如果前一个节点为空
    if (prev == null)
        // 将头节点置为空
        first = null;
    else
        // 将前一个节点的指针置为空
        prev.next = null;
    // 链表大小减1
    size--;
    // 修改计数器加1
    modCount++;
    // 返回被删除节点的数据
    return element;
}

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    linkedList.add(1,"王五");
    linkedList.addFirst("赵六");
    linkedList.addLast("唐七");

    //移除并返回列表的最后一个元素
    System.out.println(linkedList.removeLast());
    //输出此列表的全部数据
    System.out.println(linkedList);
}

set(int index,E element)

源码分析:

将此列表中指定位置的元素替换为指定的元素

public E set(int index, E element) {
    //检查索引是否越界
    checkElementIndex(index);
    // 获取指定索引的节点
    Node<E> x = node(index);
    // 获取原节点的值
    E oldVal = x.item;
    // 将指定索引的节点的值设置为新值
    x.item = element;
    // 返回原节点的值
    return oldVal;
}
 private void checkElementIndex(int index) {
     // 如果索引越界
    if (!isElementIndex(index))
        //抛出IndexOutOfBoundsException异常
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
    Node<E> node(int index) {
        // assert isElementIndex(index);
		// 如果指定索引小于链表长度的一半,则从头节点开始遍历
        if (index < (size >> 1)) {
            Node<E> x = first;
            for (int i = 0; i < index; i++)
                x = x.next;
            return x;
            // 如果索引大于等于链表长度的一半,则从尾节点开始遍历
        } else {
            Node<E> x = last;
            for (int i = size - 1; i > index; i--)
                x = x.prev;
            return x;
        }
    }

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    linkedList.addFirst("赵六");
    linkedList.addLast("唐七");
    System.out.println("原数据:"+linkedList);

    //指定位置的值替换为指定的元素
    linkedList.set(2,"小明");
    System.out.println("修改后的数据:"+linkedList);
}

size()

源码分析:

返回此列表的元素个数

public int size() {
    //返回链表的长度
    return size;
}

案例:

public static void main(String[] args) {
    LinkedList linkedList = new LinkedList();
    linkedList.add("张三");
    linkedList.add("李四");
    linkedList.addFirst("赵六");
    linkedList.addLast("唐七");

    System.out.println(linkedList.size());
}

线程安全

LinkedList不是线程安全的,如果需要在多线程环境下使用LinkedList,需要使用Collections.synchronizedList方法将其包装成线程安全的List

List<String> linkedList = new LinkedList<>();
List<String> synchronizedList = Collections.synchronizedList(linkedList); 

观众老爷看完觉得不错点个赞
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/10509.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Carla仿真二:Carla多视图切换代码详解

文章目录前言一、Carla多视图切换效果二、Camera安装坐标系1、Carla.Location2、Carla.Rotation三、接口及代码详解1、接口介绍2、生成上帝视图代码3、生成Camera视图代码四、完整代码前言 1、Carla提供了大量的Python API接口&#xff0c;用户可以通过查找文档实现各类功能&a…

无限制翻译软件-中英互译字数无限

翻译软件是我们工作及学习中必不可少的工具&#xff0c;然而许多翻译软件在使用时常常会出现字数限制的问题,这使得用户在处理长文本和大量文本时变得十分麻烦。如果你也遇到了类似的问题&#xff0c;那么哪个翻译软件不限制字数将为您带来全新的翻译体验。 以下是我们的哪个翻…

Vite打包后直接使用浏览器打开,显示空白问题

vite打包后&#xff0c;直接用浏览器打开显示空白 1.需求&#xff1a; 安卓webview等浏览器直接打开文件显示 2.原因 &#xff08;1&#xff09;资源路径错误&#xff1a; vite.config.js 配置 base: “./” &#xff08;在webpack中则配置publicPath: "./"即可…

ATTCK v12版本战术实战研究——提权(一)

一、概述 前几期文章中&#xff0c;我们中介绍ATT&CK 14项战术中提权战术&#xff08;一&#xff09;&#xff0c;包括提权前6项子技术。那么从前文中介绍的相关提权技术来开展测试&#xff0c;进行更深一步的分析。本文主要内容是介绍攻击者在运用提权技术时&#xff0c;…

算法 贪心2 || 122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II

122.买卖股票的最佳时机II 如果想到其实最终利润是可以分解的&#xff0c;那么本题就很容易了&#xff01; 如何分解呢&#xff1f; 假如第0天买入&#xff0c;第3天卖出&#xff0c;那么利润为&#xff1a;prices[3] - prices[0]。 相当于(prices[3] - prices[2]) (prices[2…

【华为OD机试】1043 - 从单向链表中删除指定值的节点

文章目录一、题目&#x1f538;题目描述&#x1f538;输入输出&#x1f538;样例1&#x1f538;样例2二、代码参考作者&#xff1a;KJ.JK&#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &am…

8D和A3报告

8D和3A报告&#xff0c;他们都不仅仅是记录问题的一种文书&#xff0c;而是解决问题的工具。 A3发展于TPS &#xff08;Toyota Production system&#xff09;&#xff0c;可以用来解决问题&#xff0c;沟通&#xff0c;记录&#xff0c;是一种流程&#xff0c;当人们在使用A3…

自定义类型详解

目录 一 结构体 1.1 结构的基础知识 1.2 结构的声明 1.3 特殊的声明 1.4 结构的自引用 1.5 结构体变量的的定义和初始化 1.6 结构体内存对齐 1.7 修改默认对齐数 1.8 结构体传参 二 位段 2.1 什么是位段 2.2 位段的内存分配 2.3 位段的跨平台问题 三 枚举 3.1 枚…

JAVA本地监听与远程端口扫描的设计与开发

随着Internet的不断发展&#xff0c;信息技术已成为社会进步的巨大推动力。不管是存储于服务器里还是流通于Internet上的信息都已成为一个关系事业成败的关键&#xff0c;这就使保证信息的安全变得格外重要。本地监听与远程端口扫描程序就是在基于Internet的端口扫描的基础上&a…

VMware Horizon 8 2303 - 虚拟桌面基础架构 (VDI) 和应用软件

请访问原文链接&#xff1a;https://sysin.org/blog/vmware-horizon-8/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org Version2303DocumentationRelease NotesRelease Date2023-03-30 虚拟桌面基础架构 (VDI) 和应用软件 VMw…

使用Ubuntu22.04搭建k8s环境和一些k8s基础知识

minikube搭建 基本环境 我使用virtualBox构建的ubuntu&#xff0c;选择4核4G内存minikube是一个K8S集群模拟器&#xff0c;可以快速构建一个单节点的集群&#xff0c;用于在本地测试和开发首先使用官方脚本安装docker curl -fsSL https://test.docker.com -o test-docker.sh…

Vue——模板引用

目录 访问模板引用​ v-for 中的模板引用​ 函数模板引用​ 组件上的 ref​ 虽然 Vue 的声明性渲染模型为你抽象了大部分对 DOM 的直接操作&#xff0c;但在某些情况下&#xff0c;我们仍然需要直接访问底层 DOM 元素。要实现这一点&#xff0c;我们可以使用特殊的 ref att…

【FPGA】多功能ALU

目录 实验要求 源代码 顶层模块 数据输入模块 ALU运算模块 结果处理模块 扫描数码管模块 扫描数码管顶层 分频器 数码管显示 仿真代码 结构层图 管脚配置 实验板卡&#xff1a;xc7a100tlc sg324-2L&#xff0c;共20个开关 实验要求 通过高低位控制&#xff0c;实现32位数…

Spring boot基础学习之(十八):通过shiro框架使用Mybatis实现用户的认证完整的认证流程

在上几篇文章的基础上&#xff0c;实现本次案例 注意&#xff1a;本篇文章的实现代码在几篇文章都已经详细的讲过了&#xff0c;所以在此篇文章&#xff0c;将不再有理论知识的陈述&#xff0c;更过的流程&#xff0c;如何通过代码实现连接数据库进行认证 添加本次案例所需要的…

00后也太卷了吧!进厂起薪18K,原来面试时候都说了这些......

都说00后躺平了&#xff0c;但是有一说一&#xff0c;该牛的还是牛。 这不&#xff0c;前段时间公司来了个00后&#xff0c;工作都没两年&#xff0c;跳槽起薪18K。本来还以为是个年少有为的技术大牛呢&#xff0c;结果相处一个月下来发现技术也就那样。 问起他是如何做到和老…

NumPy 数组学习手册:6~7

原文&#xff1a;Learning NumPy Array 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 六、性能分析&#xff0c;调试和测试 分析&#xff0c;调试和测试是开发过程的组成部分。 您可能熟悉单元测试的概念。 单元测试是程序员编写的用于测试其代码的自动测试。 例如&…

android jetpack Navigation的使用(java)

简介 Navigation通过图形化的方式管理配置页面的切换。 基本使用 添加依赖 implementation androidx.navigation:navigation-fragment:2.5.3implementation androidx.navigation:navigation-ui:2.5.3创建xml文件&#xff08;添加导航图&#xff09;——nav_graph.xml nav_…

六个阶段形成CRM销售漏斗,优点有哪些

CRM销售漏斗是反映机会状态以及销售效率的重要的销售管理模型。对企业来说&#xff0c;CRM销售漏斗是一个必不可少的工具。通过销售漏斗&#xff0c;企业可以跟踪和分析客户旅程的每个阶段&#xff0c;并制定相应的销售战略。下面来说说&#xff0c;什么是CRM销售漏斗&#xff…

Nginx

文章目录一、目录结构二、多进程模型和请求基本流程三、基础配置3.1 最小配置文件3.2 servername的多种匹配方式3.2.1完整匹配3.2.2通配符匹配3.2.3通配符结束匹配3.2.4正则匹配四、反向代理4.1 反向代理到外网与内网主机的配置4.2 负载均衡配置五、动静分离六、URLRewrite 伪静…

C-关键字(下)

文章目录循环控制switch-case-break-defaultdo-while-forgetchar()break-continuegotovoidvoid*returnconstconst修饰变量const修饰数组const修饰指针指针补充const 修饰返回值volatilestruct柔型数组union联合体联合体空间开辟问题利用联合体的性质,判断机器是大端还是小端enu…