Java集合类框架学习 1 —— 概述与基础

Java集合类框架学习 5.1 —— ConcurrentHashMap(JDK1.6) 以下内容,如有问题,烦请指出,谢谢! 这一篇讲1.6的ConcurrentHashMap ConcurrentHashMap是Java程序员接触得最多的有关并发和线程安全的类,它兼顾了并发的两个基本点——安全,高效,在很多地方都有用到,每一个Java程序员都应该真正掌握这个类。 虽然1.6版本过了10年多了,现有的1.8跟1.6的差异很大。不过1.6的最适合用来学习,它实现得简单直接 阅读详情

转载自https://blog.youkuaiyun.com/u011392897/article/details/54983068

Java集合类框架(Java Collection Framework)是用于实现和使用集合类的统一框架,让实现细节和方法使用尽量独立。 主要是为了降低变成复杂度,同时提升集合类的性能。 让一些不相干的API能够互相操作,减少了设计和学习新API的工作量,并促进软件重用。 这个框架包含了数十个接口以及它们的实现类,不同的实现类能够提供更多的选择性。

集合类框架的整体结构图,图中只有 interface,没有画出 class。

 

 

一、基础型接口

这部分主要是参考api docs,加上一些个人的理解。

1、Collection

可以理解为只包含一组对象且不显式保存映射关系的抽象容器。jdk里面没有直接的实现类,通常是用它来当做某些方法的参数来增强便利性和普遍性,比如Collections.min/max/synchronizedCollection,以及工具包中常用的CollectionUtils.isEmpty等等。

其他工具包中会有提供这个接口的直接实现类,比如guava的Multiset,apache commons collections的Bag。multiset/bag可以看成是一种可以成功地重复添加元素的set,这里的成功指的是add操作能改变自身,set添加重复元素不会改变自身。具体有什么用,一个常见的使用multiset的场景就是计数器,比如我要统计接口访问次数,可以用HashMultiiSet<String>。这样子和直接使用HashMap<String, Integer>很像,的确,HashMultiiSet底层也是这样实现的,不过这样使用更直接,能够更好的表达程序逻辑。

2、List

相对与Collection,增加一个核心特性,那就是每个元素都有唯一的数字下标,List的有序性是唯一数字下标带来的。

常见的有数组实现的支持随机访问的ArrayList,和双向链表实现的不支持随机访问的LinkedList。

3、Set

Set的核心特性是不能存在两个”相等“的元素,这里的”相等“怎么判断是依赖于具体实现的。在严格遵守(符合常理的实现)java api docs中写的==、equals和hashCode以及几个别的接口比如Comparable等等的规范下,”相等“可以理解为”非空用equals,空用null“。无序性不是Set的硬性要求,你喜欢也可以用List实现个Set,这样可以也可以有顺序,LinkedHashSet也能算是有顺序的Set。

4、Queue

这个接口java api docs里面说得很详细,我就搬一下。

提供了两套用于普通队列操作的方法。普通队列就是只能在尾部添加元素、在头部删除/获取元素的队列。add这一条主要是保留Collection接口的风格习惯,Collection接口都是通过抛出异常来表明不能添加删除。提供offer这套主要是因为Queue接口的实现类有个很重要的场景,那就是生产者消费者模型中任务队列,这时候应该有队列状态检查机制,返回特殊值的一套方法就利用特殊值来通知操作者队列处于特殊状态(队列空、队列满),无法完成操作。当然这种队列状态检查也可以使用异常来间接完成,不用异常个人觉得有两点:1、因为队列处于特殊状态而不能添加成功应该是一种正常状态,不需要用异常;2、异常开销大。

 

抛出异常

返回特殊值

插入add(e)offer(e)
删除头元素,并返回remove()poll()
获取头元素element()peek()

返回特殊值:对于删除和获取元素这两个操作,一般是返回null作为特殊值表示删除失败;对于插入操作,一般是返回false表示删除失败。

特别注意下add(e)这个方法,此方法是继承自Collection接口的,它是有返回值的。实际使用中根据规范来:如果是不继承Queue接口,比如Set,其add操作在add失败时可以返回false(Set中已经有equals一样的元素),也可以抛出异常(比如此Set实现不支持null元素);如果有继承Queue这一支的几个接口,那么建议add方法实现成功返回true,失败时直接抛出异常,不处理return。

5、Deque

提供双端队列功能,双端队列是头部尾部都能进行添加、删除、获取操作的队列。双端队列还可以用于实现Stack这种结构,因此在Deque接口中额外提供了Stack有关的几个方法,建议是用Deque的实现类代替遗留的Stack类。

Deque接口特殊性质跟Queue接口一样,注意几套方法的区别就行。

 

头部操作

头部操作

尾部操作

尾部操作

 

抛出异常

返回特殊值

抛出异常

返回特殊值

插入addFirst(e)offerFirst(e)addLast(e)offerLast(e)
删除头元素,并返回removeFirst()pollFirst()removeLast()pollLast()
获取头元素getFirst()peekFirst()getLast()peekLast()

双端队列Deque的功能包含了队列Queue的所有功能,但额外又引进了不同的方法,因此下面的方法在各种实现中强烈建议被实现为等价的,即:

add(e)      <--->      addLast(e)

offer(e)    <--->      offerLast(e)

remove()    <--->      removeFirst()

poll()      <--->      pollFirst()

element()   <--->      getFirst()

peek()      <--->      peekFirst()

 

对于栈操作,也是可以通过双端队列操作实现的,因此也建议下面的的方法实现为等价的,即:

push(e)     <--->      addFirst(e)

pop()       <--->      removeFirst()

peek()      <--->      peekFirst()

 

此外还添加了几个别的方法:

boolean removeFirstOccurrence(Object o):从头部开始移除第一个等于o的元素e,这里的等于指的是o==null ? e==null : o.equals(e)。如果遍历完了还没有找到等于的元素,则不改变这个Deque;如果成功移除,则返回true。

boolean removeLastOccurrence(Object o):基本同上,方向为从尾部开始。

Iterator<E> descendingIterator():返回一个和iterator方法方向相反的迭代器。通常iterator方法是从头到尾迭代,descendingIterator是从尾到头迭代。

 

6、Map

单映射、键值对,要求key不能存在”相等“的,一个key只能对应一个value,”相等“依赖于具体实现。Map可以说是逻辑上最最广义的容器,如果不知道用什么具体容器,那么用就用Map。

二、几种强化功能的子接口

1、SortedSet/SortedMap:根据Comparable或者Comparator,来将元素整体排序(Map用key排序)的容器,提供获取”最大“元素(first) ,”最小“元素(last) ,”更大“”更小“”介于中间“的部分(headXXX/tailXXX/subXXX)的方法。

2、NavigableSet/NavigableMap:继承SortedXXX,提供更多与”大小比较产生的顺序“有关的方法,出了这个接口后就很少直接实现SortedXXX了,直接实现这个更好。

3、BlockingQueue/BlockingDeque:提供阻塞和有超时返回的阻塞这两种操作,基本都是用来强化Queue/Deque,多提供两套操作。

4、TransferQueue:1.7开始才有的接口。它是一种特殊的阻塞队列,提供一种特殊的对象传递方法transfer,常规的阻塞添加是阻塞到元素被添加到队列,transfer方法则更进一步强化阻塞功能。如果当前存在一个正在等待元素的消费者线程,则立刻将元素交给这个消费者;如果没有正在等待元素的消费者线程,生成者线程会将元素放到队列尾部,并一直阻塞到这个元素被某一个消费者线程取走。

总共提供5个新的方法:

    transfer(E e):如果当前存在一个正在等待元素的消费者线程,则立刻将元素交给这个消费者;如果没有正在等待元素的消费者线程,生成者线程会将元素放到队列尾部,并一直阻塞到这个元素被某一个消费者线程取走。

    tryTransfer(E e):尝试立即将元素传递给正在等待的消费者,不是阻塞方法。如果传递成功,此方法立即返回true;如果没有正在等待的消费者,此方法立即返回false,并且不会把元素放在队列中。

    tryTransfer(E e, long timeout , TimeUnit unit):尝试在指定时间内将元素传递给正在等待的消费者。如果在指定时间内传递成功,返回true;如果在超时,则返回false,并且会将已经放到队列中的这个元素移除。

    hasWaitingConsumer():判断当前时刻是否有消费者线程正在等待获取元素,有则返回true,无则false。

    getWaitingConsumerCount():返回当前时刻正在等待获取元素的消费者线程的估计值,不是准确值,建议这个方法用于监视和响应,而不是精确的同步控制。

三、与集合类有关的其他基础知识

1、Iterable

此接口是1.5新增的,目的就是为了for-each循环(增强型for循环)。除了数组外,其他类想要使用for-each循环必须实现这个接口。

这个接口在1.8之前只有一个方法:

     Iterator<T> iterator();

此方法返回一个迭代器。

在jdk1.5之前,Collection接口中就有同样的方法,后面只是为了for-each循环才单独抽取出这个方法成为一个单独的接口,因此所有Collection的实现类都是可以不作更改直接使用for-each循环的。像ArrayList这种基于数组实现的可以利用传统for循环实现迭代器,提升迭代器以及for-each循环的效率,但是还是比直接使用传统for循环要慢些。

在1.8中新增了两个方法:

default void forEach(Consumer<? super T> action):默认实现为一个隐式包含迭代的方法,不用你显式写出迭代过程,只用关心Consumer操作。

default Spliterator<T> spliterator():返回一个分割器,用于并行迭代。

2、Iterator

所有迭代器的顶级接口。此类有三个基本方法:

boolean hasNext():是否还有没有被迭代的元素。

E next():返回下一个要迭代的元素,大多数实现中此方法会将迭代器当前指向位置往后移动一个元素。

void remove():此方法只能在一次next方法被调用后至多一次,删除之前最近的next方法返回的元素。jdk8后remove是一个default方法,默认实现中是抛出异常,变成了真正可选实现的方法。

default void forEachRemaining(Consumer<? super E> action):jdk1.8新增的方法,默认实现就是隐式迭代。

3、RandomAccess

此接口没有方法要实现,它就是一个标记,用于标记List接口的实现类,表明它能在O(1)的时间内进行通过下标获取对应的元素的操作,从而能支持一些特别的算法/操作来加速代码执行。

对于ArrayList,它实现了此接口,在通常情况下,

for (int i=0, n=list.size(); i < n; i++)

    list.get(i);

的运行速度比下面的循环要快:

for (Iterator i=list.iterator(); i.hasNext();)

    i.next();

所以在ArrayList中有很多直接写普通for循环的操作。java.util.Collections这个工具类中对List进行操作时大都会用 instanceof RandomAccess 区别是否实现RandomAccess接口,从而使用不同的实现。

集合类的for-each循环(增强型for循环)底层也是用迭代器实现的,所以ArrayList的for (int i=0, n=list.size(); i < n; i++)通常是比for(E e : list)要快。

关于上面三个,可以看下我之前写的这篇博文,简单分析for-each循环(非Stream中的foreach方法)的实现原理。

4、集合类与线程安全

线程安全的定义有很多版本,本人找一个认可性权威性比较高的定义:

     当多个线程访问某个类是,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。

出自《Java并发编程实战》(Java Concurrency in Practice)中文译本第13页。

 

在另外一本国内Java中知名度很高的书《深入理解Java虚拟机》中,对给出了线程共享数据的5种分类:

不可变:类似java.lang.String这种,一旦创建,这个类的对外可见的数据就不会改变了,这种肯定是数据安全的。

绝对线程安全:满足上面线程安全定义的类,常见的又符合规范的工具类、无状态的类,这种多数是没有可共享改变的类变量的类,实际上不共享可以被修改的数据,所以线程安全。

相对线程安全:类的每一个单独的操作都满足上面定义的线程安全,组合操作可能会出现问题,不满足上面定义,仍然需要进行额外同步保证线程安全,这种就是常说的”线程安全“。常见的就是下面这些集合类 Vector/Hashtable/Collections.syncXXX,它们的方法实际上都是同步的;ConcurrentHashMap提供的简单的写操作是没问题的,但是putAll/clear实际上相当于是组合操作,严格来说它是为了并发而设计的集合类,线程安全是并发中很重要的一点,但是性能也是非常重要的一点,ConcurrentHashMap为了性能,牺牲了一些线程安全性。

线程兼容:普通的类,自身没有进行线程安全控制,需要外控制。

线程对立:就是不能多线程运行的类,这种基本上设计上就不会设计出来,所以基本上没有。

集合类中几个自带的”线程安全“类都不是绝对线程安全的,有时候(最常见的就是各种方法的组合操作)还是会出问题的,自己根据实际业务分析把握下。

5、modCount与ConcurrentModificationException

modCount用于记录这个集合类的修改次数,它是单调递增,这样可以避免直接使用size/count造成的ABA问题。当集合类被修改时,这个数字会变化,通常是自增1。这里的修改指的是改变结构的修改,像ArrayList的set,HashMap的put相同的key,这些都不算是集合类本身结构的修改,不会改变modCount(ConcurrentHashMap的replace,相当于set操作或者是put相同的key,从1.7开始会改变Segment.modCount,但是它的迭代器是弱一致性、不会抛出并发修改异常的,Segment.modCount主要用于在size、containsValue方法中快速检测到Segment的改变)。这样看来modCount相当于是乐观锁中的版本号/时间戳一类的,当前的值和预期的值不一样时,说明集合类被修改过了。

 

大多数实现类中,主要是在迭代器中使用modCount检测修改,迭代器提供的remove/add等方法都是不应该修改modCount的,所以碰到modCount被修改了说明是别的线程修改了集合类(一些不好的集合类实现、写得不好的代码中,自己这个线程也是能在迭代中修改modCount的)。当检测到modCount不一样时,如果直接抛出ConcurrentModificationException异常,这个迭代器就是fail-fast快速失败的,这种迭代器能够尽量保证集合类迭代的一致性。有些实现类,比如ConcurrentHashMap,它的迭代器的实现中没有使用modCount,迭代器迭代时,如果map被修改,有可能会反映到迭代过程中,碰见这种情况,它是不会抛出ConcurrentModificationException异常的。这会导致它的迭代过程有可能和预期的不一致,它这种迭代器称为weakly consistent弱一致性迭代器。

非同步、并发设计的集合类,它们的迭代器的快速失败行为是不能被严格保证的,并发修改时它会尽量但不100%保证抛出ConcurrentModificationException。因此,依赖于此异常的代码的正确性是没有保障的,迭代器的快速失败行为应该仅用于检测bug。

实际中这个modCount机制是个很弱的检测机制,主要用在一些不太紧要的地方,提供不太严格的检测功能,或者用于检测错误。另外,在很多实现中modCount并不是volatile变量,也不是严格保证在真正的修改操作之前执行。一个集合类保证了这两点,能强化这个机制,但是你应该知道,多线程操作时应该优先使用那些为并发设计的集合,而不是依靠这个简单的机制来保障你业务代码。需要强一致性的迭代时,可以自己加锁,或者用CopyOnWirteXXX这种更偏向于并发迭代的集合。

6、equals、hashCode和==

这个搬下java api docs的,算是比较重要的基础。

equals的通常规定(实际上就是标准规定)是:

对于非空对象,它的equals应该具有以下性质:

    自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true;

    对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true;

    传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true;

    一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。

     null:对于任何非空引用值 x,x.equals(null) 都应返回 false。

Object 类的 equals 方法实现的是对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。

注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的通常规定中的“equals相等的对象必须具有相等的hashCode”。

 

hashCode的通常规定是:

    在 Java 应用程序执行期间,对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致;

    如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果;

    如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等(unequal)的对象生成不同整数结果可以提高哈希表的性能。

实际上,由 Object 类定义的 hashCode 方法确实会针对不同(!=)的对象返回不同的整数(这一般是通过将该对象的内部地址转换成一个整数来实现的)。

 

遵守上面的这两个规定时,hashCode并不是一个准确的判别对象是否相等的方法,equals在判别是否相等时的优先级是绝对高于hashCode的,所以绝大多数的地方都只用equals方法判别是否相等。但是在HashMap/HashSet中,hash值(一般由hashCode通过运算生成,可以理解为hashCode)的优先级是高于equals的(判别相等时先判别hash值,hash值相等时,再判断equals/==)。遵守这两个方法的通常规定对于HashXXX这几个集合类的使用是很重要的,这样能避免出现很多奇怪的逻辑错误。在遵守规定时,HashXXX中判别相等的实际语义就等价于equals/==,这样看起来就正常多了。

 

7、Comparable和Comparator

SortedXXX/NavigableXXX以及很多Arrays.sort方法都依赖这个。自然排序指的是类实现了Comparable,具体的可以看下java api docs,这里简单说下。

a > b    <--->    a.compareTo(b) > 0

a = b    <--->    a.compareTo(b) = 0

a < b    <--->    a.compareTo(b) < 0

这个是通常规定,也可以直接叫标准规定。

另外还有一条,叫作与 equals 的一致性,这一条性质指的是:

a.equals(b) = true    <--->    a.compareTo(b) = 0

这一条平时不用遵守,比如基于人的年龄比较,相等的年龄的人在很多逻辑中不一定是”相等“(equals = true)的。但是在TreeMap以及TreeSet中,这一条很重要,因为它的实现是基于红黑色(二叉搜索树的一种)实现的,compareTo方法的结果在这里就是唯一的判别标识。如果两个对象a, b,有a.compareTo(b) = 0但是a.equals(b) = false,那么在TreeMap中用a和b作为key时,它们实际上同一个key,它们是TreeXXX中是逻辑上”相等“的,可以互相替换。但是在外面的大多数逻辑中它们又不是”相等“(equals = true) 的,这就造成了逻辑不一致。所以使用TreeMap/TreeSet等基于排序树的实现类,注意下你的compareTo/compare方法。

 

Comparator接口是在一个类没有实现Comparable接口时,提供一个外部比较方法,方便程序实现以及程序变更,其他的和Comparable一样。

 

6、7两点,如果你对这些接口/方法规定觉得麻烦了,用String/Integer,或者直接使用的它们的equals/hashCode/compareTo去实现对应方法的类,作为你的Map的key,是个很好的办法,它们是能够完全遵守这些规定的。

 

8、数据结构和算法

这个不说了,自己看书。

 

四、其他知识

除了jdk中自带的集合类的使用及实现源码,你还需要学会使用java.util.Collections和java.util.Arrays这两个类,同时过一下里面的代码,对与集合类的理解与学习很有帮助。

其他工具包中,常用的与集合类有关的,日常使用推荐apache commons collections以及guava commom collect。它们是java集合类框架很好的扩展,同时封装了很多工具方法与新功能的集合类,功能强大,简单学习下,过下其中的部分代码也是很有必要的。

Java集合类详解:概述、优点、实现与应用 Java集合类提供了动态存储、高效的数据访问和操作等特性,大大简化了开发过程并提高了代码效率。本文将从多个方面详细介绍Java集合类的概念、基本结构、常见实现、操作方法以及性能优化和扩展,帮助读者全面掌握和应用这一关键工具。 阅读详情

相关推荐

Java集合类框架矩阵图解析

Java集合框架(Java Collections Framework)是一组接口和类,用于在Java程序中存储和操作数据集合。集合框架为Java开发者提供了一套统一的数据操作标准,简化了数据存储结构的操作过程。这一框架的存在,使得处理复杂数据集合变得更为高效和安全。在Java集合框架中,接口是定义了一组方法的契约,这些方法可以被不同的类实现。接口中的方法都是抽象的,意味着它们只声明了方法的签名而没有具体实现。

weixin_42376614的博客 1055

Java集合学习详解(2023年史上最全版)

2023最新java集合学习详解 史上最全版hashMap详解

大龄烤红薯的博客 492

肿瘤基因组分析实战:VAF、MAF、CCF这些指标到底怎么算?(附Python代码示例)

本文通过Python代码示例,详细解析了肿瘤基因组分析中VAF、MAF和CCF三大核心指标的计算逻辑与应用。文章从VCF文件解析入手,逐步演示了变异等位基因频率、次等位基因频率及癌细胞分数的计算方法,并探讨了拷贝数变异对结果的影响及克隆结构推断的实战流程,为生物信息分析提供实用指南。

silver的专栏 1005

Java集合框架学习笔记

本文摘要:Java集合框架提供了动态可变、功能丰富的容器,与固定长度的数组形成对比。核心Collection接口分为List(有序可重复)和Set(无序不重复)。文章详细介绍了集合的常用方法、四种遍历方式(迭代器、增强for、Lambda、普通for)及注意事项,重点分析了List的特有功能和ArrayList与LinkedList的底层实现差异(数组vs链表)。针对不同场景给出了选择建议:查询多用ArrayList,增删多用LinkedList。最后强调了理解数据结构(栈、队列)和实际编码练习的重要性,并

m0_75010111的博客 510

谷歌账号国家或地区设置修改全攻略:条件、流程与避坑指南

谷歌账号的国家或地区设置与付款资料、账号历史行为及登录环境强绑定,修改时需满足特定条件。其原理在于地区作为索引键,关联内容库、货币结算和风控策略。正确切换可解决内容推荐错乱、付款失败等问题,适用于搬家、订阅区域限定服务等场景。操作前需在目标地区创建付款资料、清空余额并取消订阅,且一年仅能修改一次。本文详解从准备到验证的完整流程,并揭示官方文档未提及的实操陷阱,助你安全完成地区切换。

weixin_42521558的博客 2261

ESP32-P4实战:LVGL V9.4 PPA加速配置与性能对比

本文详细介绍了如何在ESP32-P4平台上配置LVGL V9.4的PPA硬件加速功能,通过启用PPA加速显著提升图形处理性能并降低CPU占用率。文章包含环境准备、配置步骤、性能对比及常见问题解决方案,帮助开发者高效利用ESP32-P4的PPA加速器优化嵌入式GUI应用。

rice5的博客 1189

Java核心类 - 集合 学习笔记

Collection集合包括有List和Set两种,是单列集合,每个元素包含一个值。LinkedHashSet集合特点:有序、不重复、无索引。:HashSet 默认不能对内容相同的两个不同对象去重。:增强for循环,本质是迭代器遍历集合的简化写法。HashSet集合特点:无序、不重复、无索引。TreeSet集合特点:排序、不重复、无索引。Set集合特点:无序、不重复、无索引。方法结合Lamdba对集合对象遍历。:让内容相同的两个对象的哈希值相同。)遍历集合的专用方法。方法一:让自定义类实现。

qq_51800384的博客 926

SpringBoot整合JWT实战:从零构建无状态认证系统,详解Token生成、验证与安全最佳实践

JWT在SpringBoot中的实现与应用 摘要:本文介绍了JWT(JSON Web Token)的基本概念、与Session机制的对比,以及SpringBoot项目中JWT的整合实现。JWT由Header、Payload和Signature三部分组成,具有无状态、跨域支持等优势。文章详细展示了如何在SpringBoot项目中配置JWT环境,封装JWT工具类来实现Token的生成、解析和验证功能,包括密钥管理、自定义声明、签名验证等核心操作。通过对比表格和生活化比喻,帮助读者理解JWT与传统Session的

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 1774

Java集合的学习笔记与总结

集合种类 集合的父接口有两个,一个是Collection接口,另一个是Map接口。 List的特点 有序 有下标 元素可重复 Set的特点 无序 无下标 元素不能重复 List的实现类 ArrayList LinkedList Vector Set的实现类 HashSet SortSet中的TreeSet Collection父接口 方法 boolean add(Object obj) 添加一个对象 boolean addAll(Collection c) 将一个集合中的所有对象添加

m0_56085369的博客 159

芒果YOLO11改进44:主干Backbone篇之MobileViT::结合最新 ICLR2022 顶会|轻量通用的MobileViT结构(一)Transformer,轻量级、通用且移动友好的视觉转换

MobileViT::结合最新 ICLR2022 顶会|轻量通用的MobileViT结构(一)Transformer,轻量级、通用且移动友好的视觉转换

包括YOLOv5、YOLOv7、YOLOv8等模型改进 369

69页完整版智慧港口综合解决方案

智慧港口需求4港机远程操控等自动化改造需求自动化码头AGV无线通信及专用视频系统需求安全生产视频监控类需求港机RCMS及设备管理需求岸边智能理货码头三维全景应用智慧港口解决方案5自动化码头AGV/跨运车/无人集卡无线接入港机远控视觉及冗余无线通信视觉集卡防吊起系统集装箱码头岸边智能理货港机RCMS系统无线接入港机智能化管理(无线高清视频监控、一键报警、远程抄表系统)港口拖轮无线接入岸边溢油监测系统TD-LTE覆盖及业务终端接入港口生产管理系统港口可视化集群调度港口GiNMS综合网络设备智能管理全球作业效率最

zuoan1993的博客 2128

一篇文章来你学完Java中的集合(超详细)

存储的是引用:Java集合存储的是对象的引用,而不是对象本身。操作的是引用:对集合的操作(如添加、获取、更新、删除)实际上是在操作这些引用。影响垃圾回收:集合中存储的引用会影响对象的垃圾回收过程,因为只要引用存在,对象就不会被回收。ListJava中的Set集合主要用于存储不重复的元素。Set接口继承自Collection接口,但它不保证维护任何特定的顺序(除非该集合是某个特定类型的,比如,它按照元素被插入的顺序来遍历元素)。Set接口的实现类主要有HashSetTreeSet等。

2301_79842503的博客 4461

【实战圣经】YOLOv8-pose姿态估计模型从训练到RK3588部署:让边缘端骨骼识别速度突破60FPS

本教程从“模型训练-转换-边缘部署”全链路拆解了YOLOv8-pose姿态估计方案在RK3588上的落地过程,每一步都经过实战验证。无论是智能健身的动作实时纠正,还是工业设备的关键部件姿态检测,这套流程都能让你以最低成本实现高精度、高实时性的姿态估计应用。如果你在实践中遇到模型转换报错、部署性能不达标等问题,可聚焦某一环节深入优化——毕竟,让AI在边缘端“精准捕捉每一个关键点”,才是技术驱动场景创新的核心。

m0_71589036的博客 251

Java集合类详解

Collection ├List │├LinkedList │├ArrayList │└Vector │ └Stack └Set Map ├Hashtable ├HashMap └WeakHashMap Collection接口   Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Element

毛凡的博客 17万+

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

JAVA中集合类概述

这篇文章是根据张席主编的《JAVA语言程序设计教程》提炼出来的一些JAVA中集合的知识,还会加上我在编程过程中的遇到的问题和使用心得,如有错误欢迎指正。JAVA中的集合类可以分为两大类: 一类是实现Collection接口;另一类是实现Map接口。Collection是一个基本的集合接口,Collection中可以容纳一组集合元素(Element)。Map没有继承Collection接口,与Collection是并列关系。Map提供键(Key)到值(Value)的映射。

weixin_62438655的博客 4457

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

java集合类概述

集合类概述目录:集合类概述 集合的由来 由对象数组引入集合的概念 数组和集合的区别 集合的体系结构 Collection的功能概述 代码实现 集合的由来:由对象数组引入集合的概念:我们学习的是面向对象语言,而面向对象语言对事物的描述是通过对象体现的,为了方便对多个对象进行操作,我们就必须把这多个对象进行存储。而要想存储多个对象,就不能是一个基本的变量,而应该是一个容器类型的变量,在我们目前所学过的知

和而不流 763

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

JAVA集合类框架

1 问题提出        通常,程序总是根据运行时才知道的某些条件去创建新对象。在此之前,不会知道所需对象的数量,甚至不知道确切的类型。如何解决这个问题呢?即如何在任意时刻和任意位置创建任意数量的对象? Java类库提供了一套完整的容器类/集合类来解决这个问题。 2 集合框架中的接口(java.util)         所谓框架就是一个类库的集合。集合框架就是一

公众号(猴子数据分析) 2595

Java基础-集合类-概述

Java工程师知识树 / Java基础 1.为什么要用集合类 Java编程思想中指出: 通常,程序总是根据运行时才知道的某些条件去创建新对象。 在此之前,不会知道所需对象的数量,甚至不知道确切的类型。 为解决这个普遍的编程问题,需要在任意时刻和任意位置创建任意数量的对象。 所以,就不能依靠创建命名的引用来持有每一个对象: MyType aReference; 因为你不知道实际上会需要多少这样的引用。 大多数语言都提供某种方法来解决这个基本问题。Java有多种方式保存对象(应该说是对象的引用)。例如前

hughjin 544

Java集合类的概述

前述   复习一下Java中的集合类,是面试笔试中常考察的一个点,特地做的整理。 什么是集合类?   集合类,也叫容器类。Java集合类可以用来存储数量庞大的对象。   我们和数组进行对比:   数组:存储基本数据类型,数据类型单一,长度固定,不能动态增大容量。   集合:存储的即可是基本类型的值,也可以是对象,可以存储多种数据类型,长度可变,可以动态增大容量。 Ja...

weixin_30420305的博客 227

Java中有哪些集合类?常用的几种java集合类总结 详细解读 Java 的集合类

Java 的集合框架是一个统一的架构,用于表示和操作一组对象。它提供了多种接口和类,遵循了一定的设计原则,具备更高的灵活性和可扩展性。Collection:集合的根接口。List:有序集合,允许重复元素。Set:不允许重复元素的集合。Map:键值对集合,键唯一但值可以重复。Queue:用于表示数据结构中的队列。Java 集合类框架为开发者提供了强大的工具,以方便有效地操作数据。通过理解每种集合接口及其实现的特性,可以帮助我们在开发过程中做出更好的选择。

智通全网络工作室的博客 2095

【Java集合框架 一】Java集合类概述

Java中的集合主要分为以下集合类:Map、List、Set、Queue和JUC包下供多线程环境下使用的以上几种集合类,JUC包下的相关类我在另一篇JUC下集合类相关的Blog详细介绍过,本篇Blog重点介绍Java单线程环境下的几种集合类。我们知道数组是很常用的一种的数据结构,我们用它可以满足很多的功能,但有时我们会遇到如下这样的问题: 我们需要该容器的长度是不确定的,在添加数据时也不确定需要添加多少。 我们需要它能自动排序,添加数据进行是有序的 我们需要存储以键值对方式存在的数据。 这些数组类都满足

MaoLin Tian's Blog 515

Java集合类 —— 集合类概述

0. 前言 Java集合类 1. Java集合类库图 2. 集合类库概述

waynelu92的博客 519

Java学习——Java集合类概述

本文主要讲Java三个集合类:Set、 Map、 List java.util包中提供了一些集合类,这些集合类又被称为容器,提到容器不难想到数组. 1.集合类与数组的不同之处: 数组的长度是固定的,集合的长度是可变的; 数组用来存放一些基本类型的数据,集合用来存放对象的引用

qq_42102911的博客 228

Java集合类面试题: 集合容器-概述

收集大量Java经典面试题目,内容涵盖了包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 等知识点。适合准备Java面试的读者参考和复习。

m0_46013789的博客 1270
上一篇: 【转载】JDK8 ConcurrentHashMap.computeIfAbsent 死循环 Bug
下一篇: Java集合类框架学习 2 —— ArrayList(JDK1.8/JDK1.7/JDK1.6)
farmering
博客等级 码龄15年 18粉丝 23原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值