Java集合类源码阅读(一)

news2024/11/29 10:57:39

文章目录

  • 一. Iterator(迭代器)
    • 1. Iterator源码
    • 2. ListIterator源码
  • 二. Collection
  • 三. List
  • 四. Vector

在阅读源码之前,我们首先需要知道,java集合的一个继承关系图,如下所示
在这里插入图片描述
然后按照个集合关系图,逐步阅读源码,分析其设计思想。

一. Iterator(迭代器)

1. Iterator源码

public interface Iterator<E> {
    boolean hasNext();
    E next();
    default void remove() {
        throw new UnsupportedOperationException("remove");
    }
    default void forEachRemaining(Consumer<? super E> action) {
        Objects.requireNonNull(action); //检查指定的对象引用是否不是 null。此方法主要用于在方法和构造函数中执行参数验证
        while (hasNext())
            action.accept(next());
    }
}

hasNext:判断迭代器中是否还有更多的元素(即当前元素的后面是否还有元素),如果有则返回true
next:返回迭代器中的下一个元素
remove:该方法会将上一个调用next()方法时返回的元素从集合中删除。需要注意的是,只有在调用了next()方法后才能调用remove()方法,否则会抛出IllegalStateException异常

2. ListIterator源码

该接口继承至Iterator接口,并对其功能进行了拓展

public interface ListIterator<E> extends Iterator<E> {
    boolean hasNext();
    E next();
    boolean hasPrevious();
    E previous();
    int nextIndex();
    int previousIndex();
    void remove();
    void set(E e);
    void add(E e);
}

hasPrevious:判断当前元素前面是否还有元素
E previous():返回前面一个元素
nextIndex():返回下一个元素在集合中的索引
set:替换由指定元素返回next的previous最后一个元素或用指定元素返回的最后一个元素(可选操作)。仅当上次调用 或 previous之后既未调用 也未remove调用 时add,才能进行此调用next。
add:将指定的元素插入到列表中(可选操作)。该元素紧接在将由 next返回的元素之前(如果有),以及将由 返回的元素 previous(如果有)之后。

二. Collection

public interface Collection<E> extends Iterable<E> {
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);
    boolean add(E e);
    boolean remove(Object o);
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
    boolean removeAll(Collection<?> c);
    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }
    boolean retainAll(Collection<?> c);
    void clear();
    boolean equals(Object o);
    int hashCode();
    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, 0);
    }
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
    default Stream<E> parallelStream() {
        return StreamSupport.stream(spliterator(), true);
    }
}

int size(): 返回该集合中元素的数量。
boolean isEmpty(): 如果该集合不包含任何元素,则返回 true,否则返回 false。
boolean contains(Object o): 如果该集合包含指定的元素,则返回 true。
Iterator<E> iterator(): 返回一个迭代器,用于遍历该集合中的元素。
Object[] toArray(): 返回一个包含该集合中所有元素的数组。
<T> T[] toArray(T[] a): 将该集合中的元素复制到指定类型的数组中,并返回该数组。
boolean add(E e): 将指定元素添加到该集合中。
boolean remove(Object o): 从该集合中删除指定的元素(如果存在)。
boolean containsAll(Collection<?> c): 如果该集合包含指定集合中的所有元素,则返回 true。
boolean addAll(Collection<? extends E> c): 将指定集合中的所有元素添加到该集合中。
boolean removeAll(Collection<?> c): 从该集合中删除指定集合中的所有元素(如果存在)。
default boolean removeIf(Predicate<? super E> filter): 从该集合中删除满足指定条件的所有元素。
boolean retainAll(Collection<?> c): 从该集合中仅保留指定集合中的元素(如果存在)。
void clear(): 删除该集合中的所有元素。
boolean equals(Object o): 如果该集合与指定对象相等,则返回 true。
int hashCode(): 返回该集合的哈希码。
default Spliterator<E> spliterator(): 返回一个 Spliterator,用于遍历该集合中的元素。
default Stream<E> stream(): 返回一个顺序流,用于遍历该集合中的元素。
default Stream<E> parallelStream(): 返回一个并行流,用于遍历该集合中的元素

三. List

List接口源码,继承了Collection接口

public interface List<E> extends Collection<E> {
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    Object[] toArray();
    <T> T[] toArray(T[] a);
    boolean add(E e);
    boolean remove(Object o);
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c);
    //从指定的索引位置开始添加元素
    boolean addAll(int index, Collection<? extends E> c);
    boolean removeAll(Collection<?> c);
    boolean retainAll(Collection<?> c);
    default void replaceAll(UnaryOperator<E> operator) {
        Objects.requireNonNull(operator);
        final ListIterator<E> li = this.listIterator();
        while (li.hasNext()) {
            li.set(operator.apply(li.next()));
        }
    }
    @SuppressWarnings({"unchecked", "rawtypes"})
    default void sort(Comparator<? super E> c) {
        Object[] a = this.toArray();
        Arrays.sort(a, (Comparator) c);
        ListIterator<E> i = this.listIterator();
        for (Object e : a) {
            i.next();
            i.set((E) e);
        }
    }
    void clear();
    boolean equals(Object o);
    int hashCode();
    E get(int index);
    E set(int index, E element);
    void add(int index, E element);
    E remove(int index);
    int indexOf(Object o);
    int lastIndexOf(Object o);//这表示List集合的元素是可以重复的
    ListIterator<E> listIterator();
    ListIterator<E> listIterator(int index); //返回集合迭代器
    List<E> subList(int fromIndex, int toIndex);//返回指定索引范围中的元素
    @Override
    default Spliterator<E> spliterator() {
        return Spliterators.spliterator(this, Spliterator.ORDERED);
    }
}

四. Vector

Vector是一种基本的数据结构,它是一种动态数组,可以在运行时自动扩展和收缩。Vector可以存储任何类型的对象,包括基本数据类型和自定义类的对象。在Java中,Vector的capacity表示它的存储容量,而capacityIncrement表示向量的容量增量。当创建一个Vector对象时,它的capacity是固定的。如果在向量中添加元素时,超过了其当前容量,则会自动扩展其容量。在扩展容量时,如果指定了capacityIncrement,则会按照该增量来增加容量。如果没有指定capacityIncrement,则会将当前容量加倍来扩展容量。例如,如果创建一个初始容量为10的Vector,并且指定容量增量为5,则当添加第11个元素时,Vector的容量将自动扩展到15。如果没有指定容量增量,则容量将增加到20。可以使用Vector类的capacity()方法来获取当前容量,而使用capacityIncrement()方法来获取容量增量。此外,还可以使用ensureCapacity()方法来确保Vector具有足够的容量,以便存储指定数量的元素,而不需要进行容量调整

public class Vector<E>
    extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
 //创建一个Object数组,说明Vector的底层是数组
    protected Object[] elementData;  
 //定义元素数量
    protected int elementCount;
 //用于处理Vector结合自增,即每次vector元素自增的步伐
    protected int capacityIncrement;
    private static final long serialVersionUID = -2767605614048989439L;
    //构造函数
    public Vector(int initialCapacity, int capacityIncrement) {
        super();
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        this.elementData = new Object[initialCapacity];
        this.capacityIncrement = capacityIncrement;
    }
    //构造函数
    public Vector(int initialCapacity) {
        this(initialCapacity, 0);
    }
    //默认构造函数
    public Vector() {
        this(10);
    }
    //用另一个集合来构造Vector集合
    public Vector(Collection<? extends E> c) {
        Object[] a = c.toArray();  //将集合c转换为数组形式
        elementCount = a.length; 
        if (c.getClass() == ArrayList.class) {//c的类型和Arraylist则直接赋值
            elementData = a;
        } else {
        //否则直接拷贝使用
            elementData = Arrays.copyOf(a, elementCount, Object[].class);
        }
    }
    //将数组从指定的源阵列(从指定位置开始)复制到目标阵列的指定位置,可以看出是线程安全的
    public synchronized void copyInto(Object[] anArray) {
        System.arraycopy(elementData, 0, anArray, 0, elementCount);
    }
    //trimToSize()方法,它用于将Vector对象的容量调整为当前Vector中实际元素的数量。换句话说,它可以将Vector的容量缩小到与其大小相同,从而节省内存空间
    public synchronized void trimToSize() {
        modCount++;
        int oldCapacity = elementData.length;
        if (elementCount < oldCapacity) {
            elementData = Arrays.copyOf(elementData, elementCount);
        }
    }
   
    public synchronized void ensureCapacity(int minCapacity) {
        if (minCapacity > 0) {
            modCount++;
            ensureCapacityHelper(minCapacity);
        }
    }
    private void ensureCapacityHelper(int minCapacity) {
        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
    //该函数用于设置Vector的容量(这个方法不是线程安全的)
    private void grow(int minCapacity) {
    //获取旧的vector的容量
        int oldCapacity = elementData.length;
    //容量增加,如果capacityIncrement大于0则增加capacityIncrement,否则就是原来容量扩容
        int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
                                         capacityIncrement : oldCapacity);
        //如果新的容量小于指定的最小容量,则将新容量扩容成指定的最小容量
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
            //如果新的容量大于了MAX_ARRAY_SIZE,调用hugeCapacity函数(下面有)
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        //重写设置集合
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }
    public synchronized void setSize(int newSize) {
        modCount++;
        if (newSize > elementCount) {
            ensureCapacityHelper(newSize);
        } else {
        //指定的新的容量小于本来的容量,则将newSize后面的内容设置为空
            for (int i = newSize ; i < elementCount ; i++) {
                elementData[i] = null;
            }
        }
        elementCount = newSize;
    }
    //返回当前容器的实际容量
    public synchronized int capacity() {
        return elementData.length;
    }
    public synchronized int size() {
        return elementCount;
    }
    public synchronized boolean isEmpty() {
        return elementCount == 0;
    }
    //用枚举类封装集合的一些信息
    public Enumeration<E> elements() {
        return new Enumeration<E>() {
            int count = 0;

            public boolean hasMoreElements() {
                return count < elementCount;
            }

            public E nextElement() {
                synchronized (Vector.this) {
                    if (count < elementCount) {
                        return elementData(count++);
                    }
                }
                throw new NoSuchElementException("Vector Enumeration");
            }
        };
    }
    //判断vector集合中是否包含某个元素,本质上是用indexof判断的
    public boolean contains(Object o) {
        return indexOf(o, 0) >= 0;
    }
    //返回指定元素在数组的索引
    public int indexOf(Object o) {
        return indexOf(o, 0);
    }
    //实现返回指定元素索引的具体方法实现(它是线程安全的),根据实现可以看出它是返回第一个匹配的元素
    public synchronized int indexOf(Object o, int index) {
        if (o == null) {
            for (int i = index ; i < elementCount ; i++)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index ; i < elementCount ; i++)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
    public synchronized int lastIndexOf(Object o) {
        return lastIndexOf(o, elementCount-1);
    }
    //它其实是一个逆向遍历的过程
    public synchronized int lastIndexOf(Object o, int index) {
        if (index >= elementCount)//如果索引大于实际元素数量,抛出异常
            throw new IndexOutOfBoundsException(index + " >= "+ elementCount);
       
        if (o == null) {
            for (int i = index; i >= 0; i--)
                if (elementData[i]==null)
                    return i;
        } else {
            for (int i = index; i >= 0; i--)
                if (o.equals(elementData[i]))
                    return i;
        }
        return -1;
    }
    //返回指定元素在集合中的索引
    public synchronized E elementAt(int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
        }
        return elementData(index);
    }
    //返回vector的第一个元素
    public synchronized E firstElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(0);
    }
    //返回vector的最后一个元素
    public synchronized E lastElement() {
        if (elementCount == 0) {
            throw new NoSuchElementException();
        }
        return elementData(elementCount - 1);
    }
    //替换指定索引位置的元素
    public synchronized void setElementAt(E obj, int index) {
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        elementData[index] = obj;
    }
    public synchronized void removeElementAt(int index) {
        modCount++;
        if (index >= elementCount) {
            throw new ArrayIndexOutOfBoundsException(index + " >= " +
                                                     elementCount);
        }
        else if (index < 0) {
            throw new ArrayIndexOutOfBoundsException(index);
        }
        int j = elementCount - index - 1;
        if (j > 0) {
        //将原数组的index+1位置后面的元素拷贝到原数组的index开始的位置,元素个数为j,即要删除原属后面的元素
            System.arraycopy(elementData, index + 1, elementData, index, j);
        }
        elementCount--;
        elementData[elementCount] = null; /* to let gc do its work */
    }
    //在指定的索引位置插入元素
    public synchronized void insertElementAt(E obj, int index) {
        modCount++;
        if (index > elementCount) {
            throw new ArrayIndexOutOfBoundsException(index
                                                     + " > " + elementCount);
        }
        //容量添加
        ensureCapacityHelper(elementCount + 1);
        System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
        elementData[index] = obj;
        elementCount++;
    }
    //集合末尾添加元素
    public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }
    //删除集合中与指定obj匹配的第一个元素
    public synchronized boolean removeElement(Object obj) {
        modCount++;
        int i = indexOf(obj);
        if (i >= 0) {
            removeElementAt(i);
            return true;
        }
        return false;
    }
    //删除所有元素,(将所有的元素设置为null)
    public synchronized void removeAllElements() {
        modCount++;
        // Let gc do its work
        for (int i = 0; i < elementCount; i++)
            elementData[i] = null;
        elementCount = 0;
    }
    public synchronized Object clone() {
        try {
  //@SuppressWarnings("unchecked") 是 Java 中的一个注解(Annotation),它用于告诉编译器忽略 unchecked 警告。当编译器发现代码中存在未检查的转换时(如将一个泛型类型的对象赋给一个非泛型类型的变量,或者将一个带有泛型类型参数的方法返回值赋给一个未使用泛型类型参数的变量),它会生成一个 unchecked 警告
            @SuppressWarnings("unchecked")
                Vector<E> v = (Vector<E>) super.clone();
            v.elementData = Arrays.copyOf(elementData, elementCount);
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            // this shouldn't happen, since we are Cloneable
            throw new InternalError(e);
        }
    }
   //vector对象转换为数组
    public synchronized Object[] toArray() {
        return Arrays.copyOf(elementData, elementCount);
    }
    @SuppressWarnings("unchecked")
    public synchronized <T> T[] toArray(T[] a) {
        if (a.length < elementCount)
            return (T[]) Arrays.copyOf(elementData, elementCount, a.getClass());

        System.arraycopy(elementData, 0, a, 0, elementCount);

        if (a.length > elementCount)
            a[elementCount] = null;

        return a;
    }
    //查找指定索引位置的元素,现场不安全的
    @SuppressWarnings("unchecked")
    E elementData(int index) {
        return (E) elementData[index];
    }
    //同意是返回指定索引位置的元素,但它是线程安全的
    public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index);
    }
    //设置集合指定位置的元素值
    public synchronized E set(int index, E element) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        E oldValue = elementData(index);
        elementData[index] = element;
        return oldValue;
    }
    //向vector集合的末尾添加元素
    public synchronized boolean add(E e) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = e;
        return true;
    }
    public boolean remove(Object o) {
        return removeElement(o);
    }
    public void add(int index, E element) {
        insertElementAt(element, index);
    }
    public synchronized E remove(int index) {
        modCount++;
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);
        E oldValue = elementData(index);

        int numMoved = elementCount - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--elementCount] = null; // Let gc do its work

        return oldValue;
    }
    public void clear() {
        removeAllElements();
    }
    public synchronized boolean containsAll(Collection<?> c) {
        return super.containsAll(c);
    }
    //将某个Conlleciton中的所有元素添加到当前vector集合中
    public synchronized boolean addAll(Collection<? extends E> c) {
        modCount++;
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityHelper(elementCount + numNew);
        System.arraycopy(a, 0, elementData, elementCount, numNew);
        elementCount += numNew;
        return numNew != 0;
    }
    //删除集合所有的元素
    public synchronized boolean removeAll(Collection<?> c) {
        return super.removeAll(c);
    }
    //在集合中保留指定集合的元素
    public synchronized boolean retainAll(Collection<?> c) {
        return super.retainAll(c);
    }
    //将Collection的元素从指定位置加入到集合中
    public synchronized boolean addAll(int index, Collection<? extends E> c) {
        modCount++;
        if (index < 0 || index > elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityHelper(elementCount + numNew);

        int numMoved = elementCount - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved);

        System.arraycopy(a, 0, elementData, index, numNew);
        elementCount += numNew;
        return numNew != 0;
    }
    public synchronized boolean equals(Object o) {
        return super.equals(o);
    }
    public synchronized int hashCode() {
        return super.hashCode();
    }
    public synchronized String toString() {
        return super.toString();
    }
    //返回指定位置区间的原属内容
    public synchronized List<E> subList(int fromIndex, int toIndex) {
        return Collections.synchronizedList(super.subList(fromIndex, toIndex),
                                            this);
    }
    //删除指定区间的元素
    protected synchronized void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = elementCount - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);

        // Let gc do its work
        int newElementCount = elementCount - (toIndex-fromIndex);
        while (elementCount != newElementCount)
            elementData[--elementCount] = null;
    }
    //用于反序列化
    private void readObject(ObjectInputStream in)
            throws IOException, ClassNotFoundException {
        ObjectInputStream.GetField gfields = in.readFields();
        int count = gfields.get("elementCount", 0);
        Object[] data = (Object[])gfields.get("elementData", null);
        if (count < 0 || data == null || count > data.length) {
            throw new StreamCorruptedException("Inconsistent vector internals");
        }
        elementCount = count;
        elementData = data.clone();
    }
    //用于序列化对象,是线程安全的
    private void writeObject(java.io.ObjectOutputStream s)
            throws java.io.IOException {
        final java.io.ObjectOutputStream.PutField fields = s.putFields();
        final Object[] data;
        synchronized (this) {
            fields.put("capacityIncrement", capacityIncrement);
            fields.put("elementCount", elementCount);
            data = elementData.clone();
        }
        fields.put("elementData", data);
        s.writeFields();
    }
    //线程安全的迭代器类
    public synchronized ListIterator<E> listIterator(int index) {
        if (index < 0 || index > elementCount)
            throw new IndexOutOfBoundsException("Index: "+index);
        return new ListItr(index);
    }
    public synchronized ListIterator<E> listIterator() {
        return new ListItr(0);
    }
    public synchronized Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        public boolean hasNext() {
            // Racy but within spec, since modifications are checked
            // within or after synchronization in next/previous
            return cursor != elementCount;
        }

        public E next() {
            synchronized (Vector.this) {
                checkForComodification();
                int i = cursor;
                if (i >= elementCount)
                    throw new NoSuchElementException();
                cursor = i + 1;
                return elementData(lastRet = i);
            }
        }

        public void remove() {
            if (lastRet == -1)
                throw new IllegalStateException();
            synchronized (Vector.this) {
                checkForComodification();
                Vector.this.remove(lastRet);
                expectedModCount = modCount;
            }
            cursor = lastRet;
            lastRet = -1;
        }
    //迭代器对象
    final class ListItr extends Itr implements ListIterator<E> {
        ListItr(int index) {
            super();
            cursor = index;
        }

        public boolean hasPrevious() {
            return cursor != 0;
        }

        public int nextIndex() {
            return cursor;
        }

        public int previousIndex() {
            return cursor - 1;
        }

        public E previous() {
            synchronized (Vector.this) {
                checkForComodification();
                int i = cursor - 1;
                if (i < 0)
                    throw new NoSuchElementException();
                cursor = i;
                return elementData(lastRet = i);
            }
        }

        public void set(E e) {
            if (lastRet == -1)
                throw new IllegalStateException();
            synchronized (Vector.this) {
                checkForComodification();
                Vector.this.set(lastRet, e);
            }
        }

        public void add(E e) {
            int i = cursor;
            synchronized (Vector.this) {//对当前vector对象加上对象锁
                checkForComodification();
                Vector.this.add(i, e);
                expectedModCount = modCount;
            }
            cursor = i + 1;
            lastRet = -1;
        }
    }
    //集合排序是线程安全的
    @SuppressWarnings("unchecked")
    @Override
    public synchronized void sort(Comparator<? super E> c) {
        final int expectedModCount = modCount;
        Arrays.sort((E[]) elementData, 0, elementCount, c);
        if (modCount != expectedModCount) {
            throw new ConcurrentModificationException();
        }
        modCount++;
    }
 }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

onnxruntime 运行过程报错“onnxruntime::Model::Model Unknown model file format version“

背景 这几天在玩一下yolov6&#xff0c;使用的是paddle框架训练的yolov6&#xff0c;然后使用paddl 转成onnx&#xff0c;再用onnxruntime来去预测模型。由于是在linux服务器上转出来 的onnx模型&#xff0c;并在本地的windows电脑上去使用&#xff0c;大概就是这样的一个情…

C语言中的小知识点(程序环境和预处理篇(1))

系列文章目录 文章目录系列文章目录[TOC](文章目录)前言一、编译链接是什么&#xff1f;&#xff08;一&#xff09;、翻译环境二、预处理的讲解1.预定义符号2.#define定义标识符总结前言 在ANSI C的任何一种实现中&#xff0c;存在两个不同的环境 第一种是翻译环境&#xff0c…

JavaWeb开发 —— HTML

目录 一、什么是HTML、CSS 二、内容介绍 三、基本标签 & 样式 1. 实现标题 1.1 标题排版 1.2 标题样式 1.3 超链接 2. 实现正文 2.1 正文排版 2.2 页面布局 四、表格标签 五、表单标签 1. 表单标签 2. 表单项标签 一、什么是HTML、CSS HTML ( HyperTex…

MAC 删除自带 ABC 输入法的方法

背景&#xff1a; 在使用 ​​mac​​​ 时相信很多都习惯使用第三方输入法&#xff0c;而 ​​mac​​​ 规定必须保留一个自带的 ​​ABC​​​ 输入法&#xff0c;这样导致平时在打字的时候&#xff0c;老是莫名其妙的自己切换成了自带的 ​​ABC​​​ 输入法&#xff0c;…

【java】JDK动态代理原理

文章目录1. 示例2. 原理3. 为什么必须要基于接口&#xff1f;1. 示例 首先&#xff0c;定义一个接口&#xff1a; public interface Staff {void work(); }然后&#xff0c;新增一个类并实现上面的接口&#xff1a; public class Coder implements Staff {Overridepublic vo…

Rancher v2.5 使用 Ingress Controller 限制集群外部 ip 访问集群服务

使用 Ingress Controller 限制集群外部 ip 访问集群服务 Rancher 部署工作负载&#xff0c;通过 NodePort 将 Service 服务映射后&#xff0c;无法通过防火墙策略对集群外客户端访问进行限制&#xff0c;在公司研发环境内存在风险&#xff0c;易被扫描到。 经过查找资料&#x…

HNU-操作系统OS-2023期中考试

今天考了OS期中考试&#xff0c;特别傻地最后改错了一道10分的题目&#xff0c;很难受。应该是考差了。 回忆一下今天考试的题目&#xff0c;为可能需要的后继者提供帮助&#xff08;往年期中考题极难获得&#xff09; 我这里先给出题目&#xff0c;有时间我再补充答案&#…

FVM链的Themis Pro(0x,f4) 5日IDO超百万美元,领Filecoin重回高点

交易一直是 DeFi 乃至web3领域最经久不衰的话题&#xff0c;也因此催生了众多优秀的去中心化协议&#xff0c;如 Uniswap 和 Curve。这些协议逐渐成为了整个系统的基石。 在永续合约方面&#xff0c;DYDX 的出现将 WEB2 时代的订单簿带回了web3。其链下交易的设计&#xff0c;仿…

【云原生概念和技术】1.2 云原生技术概括(中)

如果想了解或者学习云原生的友友们&#xff0c;欢迎订阅哦&#xff5e;&#x1f917;&#xff0c;目前一周三更&#xff0c;努力码字中&#x1f9d1;‍&#x1f4bb;…目前第一章是一些介绍和概念性的知识&#xff0c;可以先在脑海里有一个知识的轮廓&#xff0c;从第二章开始就…

php://filter

一 php://filter 官方&#xff1a;php://filter 是一种元封装器&#xff0c; 设计用于数据流打开时的筛选过滤应用。 这对于一体式&#xff08;all-in-one&#xff09;的文件函数非常有用&#xff0c;类似 readfile()、 file() 和 file_get_contents()&#xff0c; 在数据流内…

黑群晖激活Active Backup for Business套件 DSM6、7

​ 第一步 http://URL:PORT/webapi/auth.cgi?apiSYNO.API.Auth&methodLogin&version1&account管理员用户名&passwd密码 http://192.168.8.160:5000/webapi/auth.cgi? apiSYNO.API.Auth&methodLogin&version1&accountadmin&passwd123456 说…

Spring Boot 监控

目录 1.概述 2.使用 2.1.依赖 2.2.配置 2.2.1.默认 2.2.2.暴露端点 2.3.常用端点 2.3.1.health 2.3.2.metrics 2.3.3.loggers 2.3.4.beans 2.3.5.用于定位线上问题的端点 2.4.自定端点 1.概述 Spring Boot Actuator提供了对Spring Boot应用进行监控的能力&#…

哈希表(HashTable)

哈希表&#xff08;HashTable&#xff09;1. 相关概念2. 哈希函数选择&#xff08;常用&#xff09;3. 哈希冲突&#xff08;常用&#xff09;开散列法/哈希桶法/链地址法&#xff1a;4. Set接口及实现类4.0 常用方法4.1 HashSet4.2 LinkedHashSet4.3 TreeSet4.4 例题1. 相关概…

第八章 Attention

目录8.1 Attention 的结构8.1.1 seq2seq 存在的问题8.1.2 编码器的改进8.1.3 解码器的改进 ①8.1.4 解码器的改进 ②8.1.5 解码器的改进 ③8.2 带 Attention 的 seq2seq 的实现8.2.1 编码器的实现8.2.2 解码器的实现8.2.3 seq2seq 的实现8.3 Attention 的评价8.3.1 日期格式转换…

【数据结构】6.5 红黑树(C++)

【数据结构】——6.5 红黑树 没有学过二叉搜索树&#xff08;也叫二叉排序树或二叉查找树&#xff09;的小伙伴们建议先学习一下&#xff0c;这样阅读会更轻松哦 点我学习二叉搜索树 目录一、红黑树的概念和性质二、红黑树的存储结构和声明三、红黑树的构建过程四、红黑树的实现…

淘宝客户失率高怎么办?什么因素会影响?

电商干货 商家开淘宝店铺的时候&#xff0c;很怕的是老客户流失了。或者说经常购买的人不买了&#xff0c;这是淘宝店铺的客户流失。 那么当我们遇到淘宝的客户流失率很高的时候该怎么办呢&#xff1f;有什么样的因素会造成影响呢? 淘宝客户流失率高怎么办 1、做好质量营销 质…

Trimble RealWorks处理点云数据(七)之点云导入3dmax

效果 背景 有时候我们需要通过点云数据来逆向建模,而建模软件常用的有3dmax,SketchUp等,那如何将点云数据导入3dmax来建模呢,下面我们来了解下 步骤 1、las导入Trimble RealWorks 2、对点云数据预处理 可以参考这篇文章 TrimbleRealWorks点云数据预处理 3、导出rcp格式…

语音芯片在射击游乐设备上的应用

射击打靶体验馆项目&#xff0c;产品设备仿真程度高、趣闻性强、外观逼真&#xff0c;现场体验是一种集体验&#xff0c;体育竞技为一体且室内外均可使用的游乐&#xff01; 在靶上能够看到击中目标的效果&#xff0c;而且会语音报环靶&#xff0c;通过低音炮&#xff0c;可以…

Pytorch基础 - 6. torch.reshape() 和 torch.view()

目录 1. torch.reshape(shape) 和 torch.view(shape)函数用法 2. 当处理的tensor是连续性的(contiguous) 3. 当处理的tensor是非连续性的(contiguous) 4. PyTorch中的contiguous 在本文开始之前&#xff0c;需要了解最基础的Tensor存储方式&#xff0c;具体见 Tensor数据类…

Spring常见面试题汇总

文章目录在Spring中&#xff0c;Bean的作用域有哪几个&#xff1f;SpringMVC的执行流程你知道吗&#xff1f;谈谈你对Spring IOC的理解&#xff1f;DI又是什么&#xff1f;谈谈你对Spring AOP的理解&#xff1f;Spring Bean的生命周期你能说出多少&#xff1f;Spring如何解决循…