java集合随笔

    技术2022-07-10  138

    集合的概念: Collection接口 Set接口及其实现类 List接口及其实现类 Queue接口及其实现类 Map接口及其实现类 HashMap和HashSet的性能选项 Collection工具类 集合概述 为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组)。java提供集合类,集合类主要负责保存,盛装其他数据,因此集合类也被称为容器类。所有集合类都位于java.util包下 。 java的集合类主要由两个接口派生儿出:Collection和Map.Collection和Map是java集合的根接口,这两个接口又包含了一些子接口或实现类。 Collection<--Set(无序集合,元素不可重复) EnumSet SortedSet<--TreeSet HashSet<---LinkedHashSet Queue <--Deque<---LinkedList Queue <--PriorityQueue Collection<--List(有序集合,元素可重复) List<--LinkedList List<--ArrayList List<--Vector<--Stack Map<--EnumMap Map<--IdentityHashMap Map<--HashMap<--LinkedHashMap Map<--Hashtable<--Properties Map<--SortedMap<--TreeMap Map<--WeakHashMap Collection接口是List,Set和Queue接口的父接口,该接口里定义的方法即可用于操作Set集合,也可用于操作List和Queue集合。 Collection提供了大量添加,删除,访问的放法来访问集合元素。 Iterator接口 Iterator接口也是Java集合框架的成员,但它与Collection系列,Map系列的集合不一样: Collection系列集合,Map系列集合主要用于盛装其他对象,而Iterator则主要用于遍历(即迭代访问)Collection集和中的元素,Iterator对象也被称为迭代器。 Iterator接口里定义了如下4个方法: -boolean hasNext():如果被迭代的集合和元素没有被遍历,则返回true. -Object next():返回集合里下一个元素。 -void remove():删除集合里上一次next方法返回的元素 -void forEachRemaining(Consumer action),这是Java8为Iterator新增的默认方法,该方法可使用Lambda表达式来遍历集合元素。 foreach循环遍历集合元素 使用JDK1.5提供的foreach循环来迭代访问集合元素更加便捷。 当使用foreach循环迭代访问集合元素时,该集合也不能被改变,否则将引发ConcurrentModificationException异常。 使用Predicate操作集合 java8 为Collection集合新增了一些需要Predicate参数的方法,这些方法可以对集合元素进行过滤。程序可使用Lambda表达式构建Predicate对象。 Java8新增的Stream操作 Java8新增了Stream,IntStream,LongStream,DoubleStream等流式API。 独立使用Stream的步骤如下: -1)使用Stream或XxxxStream的builder()类方法创建该Stream对应Builder. -(2)重复调用Builder的add()方法向该流中添加多个元素。 -3)调用Builder的build()方法获取对应的Stream. -(4)调用Stream的聚集方法。 Collection接口提供了一个stream()默认方法,该方法可返回该集合对应的流,接下来即可通过流API来操作集合元素。由于Stream可以对集合元素进行整体的聚集操作,因此Stream极大了丰富了集合功能。 HashSet类 HashSet是Set接口的典型实现,大多时候使用Set集合就是使用这个实现类 。HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能。 当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该HashCode值来决定该对象在HashSet中存储位置。如果有两个元素通过equals方法比较返回true,但他们的hashCode()方法返回值不相等,HashSet将会把它们存储在不同位置,也就可以添加成功。 HashSet的特征 不能保证元素的排列顺序,顺序可能与元素的添加顺序不同,元素的顺序可能变化。 HashSet 不是同步的,如果多个线程同时访问HashSet,如果有2条或者2条以上线程同时修改了HashSet集合时,必须通过代码来保证其同步。 集合元素值可以是null. LinkedHashSet LinkedHashSet集合也是根据元素hashCode值来决定元素存储位置,但它同时使用链表维护元素的次序,这样使得元素看起来是可以插入的顺序保存的。也就是说,当遍历LinkedHashSet集合里元素时,HashSet将会按元素的添加顺序来访问集合里的元素。 LinkedHashSet 需要维护元素的插入顺序,因此性能略低于HashSet的性能,但在迭代访问Set里的全部元素时将有很好的性能,因为它以链表来维护内部顺序。 TreeSet TreeSet 是SortedSet接口的唯一实现,正如SotedSet名字所暗示的,TreeSet可以确保集合元素处于排序状态。与前面HashSet集合相比,TreeSet还提供了如下几个额外的方法: -Object first():返回集合中的第一个元素。 -Object last():返回集合中的最末一个元素。 -Object lower(Object e):返回集合中位于指定元素之前的元素(即小于指定元素的最大元素,参考元素不需要是TreeSet的元素) -Object higher(Object e):返回集合中位于指定元素之后的元素(即指定元素的最小元素,参考元素不需要是TreeSet的元素)。 -SortedSet subSet(formElement,toElement):返回此Set的子集合,范围从fromElement(包含)到toElement(不包含)。 -SortedSet headSet(toElement):返回此Set的子集,由于小于toElement的元素组成。 -SortedSet tailSet(fromElement):返回此Set的子集,由大于或等于fromElement的元素组成。 TreeSet采用红黑树的数据结构对元素进行排序。TreeSet支持两种排序方法:自然排序和定制排序。 -自然排序:TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之前大小关系,然后将集合元素按升序排列,这种方式就是自然排序。 -定制排序:TreeSet借助Comparator接口的帮助。该接口里包含一个的int compare(Tol,To2)方法,该方法用于比较o1和o2的大小。 EnumSet EnumSet是一个专为枚举类设计的集合类,EnumSet中所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnmuSet时显示或隐式地指定。EnumSet的集合元素也是有序的,EnumSet以枚举值在Enum类的定义顺序来决定集合元素的顺序。 EnumSet在内部以位向量的形式存储,这种存储形式非常紧凑,高效,因此EnumSet对象占用内存很小,而且运行效率很好。尤其是当进行批量操作(如调用containsAll和retainAll方法)时,如其参数也是EnumSet集合,则该批量操作的执行速度也非常快。 EnumSet集合不允许加入null元素。如果试图插入null元素,EnumSet将抛出NullPointerException异常。如果仅仅只是试图测试是否出现null元素,或删除null元素都不会抛出异常,只是删除操作将返回false,因为没有任何null元素被删除。 List接口 List集合代表一个有序集合,集合中每个元素都有其对应的顺序索引。List集合允许使用重复元素,可以通过索引来访问指定位置的集合元素。因为List集合默认按元素的添加顺序设置元素的索引,例如第一次添加的元素索引为0,第二次添加的元素索引为1...... List作为Collection接口的子接口,当然可以使用Colletion接口里全部方法。而且由于List是有序集合,因此List集合里包含了根据索引来操作集合元素的方法。 ListIterator与Iterator接口不同,它不仅可以向后迭代,它还可以向前迭代。 ListIterator包含增加了如下3个方法: -boolean hasPrevious(): 返回该迭代器关联的集合是否还有上一个元素。 -Object previous(): 返回该迭代器的上一个元素。 -void add():在指定位置插入一个元素。 Itrator(迭代)Enumeration(枚举) 迭代是取出集合中元素的一种方式。 因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。 用法: for(Iterator ite=iterator();iter.hasNext();) { System.out.print(iter.next()); } Iterator iter = l.iterator(); while(iter.hasNext()) { System.out.println(iter.next()); } 迭代注意事项 迭代器在Collection接口中是通用的。 迭代器的next方法是自动向下取元素,要避免出现NoSuchElementException 迭代器的next方法返回值类型是Object,所以要记得类型转换。 比较Comparator 比较Comparator 比较函数强行对某些对象collection进行整体排序。可以将Comparator传递给sort方法(如Collections.sort),从而允许在排序上实现精确控制。 public class User{ int a; String s; public User(int a,String s ){ this.a=a; this.s=s; } } ArrayList<User> arr=new ArrayList(); arr.add(new User(21,"21"); arr.add(new User(12,"12"); arr.add(new User(3,"3"); arr.add(new User(14,"14"); arr.add(new User(5,"5"); arr.add(new User(26,"26"); Collection.sort(arr); ArrayList与Vector ArrayList和Vector类都是基于数组实现的List类,所以ArrayList和Vector类封装了一个动态再分配的Object[]数组。每个ArrayList或Vector对象有一个capacity属性,这个capacity表示它们所封装的Object[]数组的长度。当向ArrayList或Vector中添加元素时,它们的capacity会自动增加。 ArrayList和Vector的显著区别是;ArrayList是线程不安全的,当多条线程访问同一个ArrayList集合时,如果有超过一条线程修改了ArrayList集合,则程序必须手动保证该集合的同步性。但Vector集合则是线程安全的,无需程序保证该集合的同步性。 固定长度的List Arrays工具类里提供了asList(Object...a)方法,该方法可以把一个数组,或指定个数的对象转换成List集合,这个List集合即不是ArrayList实现类的实例,也不是Vector实现类的实例,而是Arrays的内部类ArrayList的实例。 Arrays.ArrayList是一个固定长度的List集合,程序只能遍历访问该集合里的元素,不可增加,删除该集合里的元素。 Queue接口 Queue用于模拟了队列这种数据结构,队列通常是指,“先进先出”(FIFO)的容器。队列的头部保存在队列中存放时间最长的元素。队列的尾部保存在队列中存放时间最短的元素。新元素插入(offer)到队列的尾部,访问元素(poll)操作返回队列头部的元素。通常,队列不允许随机访问队列中的元素。 LinkedList 它是List接口的实现类这意味着它是一个List集合,可以根据索引来随机访问集合中的元素。除此之外,LinkedList还实现了Deque接口,Deque接口是Queue接口的子接口,它代表一个双端队列。 LinkedList不仅可以当成双端队列使用,也可以当成“栈”使用,因为该类里还包含了pop(出栈)和push(入栈)两个方法。除此之外,LinkedList接口,所以还被当成List使。 ArrayList与LinkedList LinkedList与ArrayList,Vector的实现机制完全不同,ArrayList,Vector内部一数组的形式来保存集合中的元素,因此随机访问集合元素上有较好的性能;而LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合元素时性能较差,但在插入,删除元素时性能非常出色(只需要改变指针所指的地址即可); 类Stack<E> java.util 类Stack<E> java.lang.Object java.util.AbstractCollection<E> java.util.AbstractList<E>java.util.Vector<E> java.utilStack<E> 所有以实现的接口: Serializable,Cloneable,Iterable<E>, Collection<E>,List<E>,RandomAccess 接口Query<E> java.util 接口Queue<E> 类型参数: E-集合中所保存的元素类型。 所有超级接口: -Collection<E>,Iterable<E> 所有已知接口: -BlockingQueue<E> 所有已知实现类: -AbstractQueue,ArrayBlockingQueue,ConcurrentLinkedQueue, DelayQueue,LinkedBlockingQueue,LinkedList, PriorityBlockingQueue,PriorityQueue,SynchronousQueue PriorityQueue PriorityQueue是一个比较标准的队列实现类,之所以说它是比较标准的队列实现,而不是绝对标准的队列实现是因为: PrioprotyQueue保存队列元素的顺序并不是按加入队列的顺序,而是按队列元素的大小进行重新排序。因此当调用peek方法或者poll方法来取出队列中的元素时,并不是取出最先进入队列的元素,而是取出队列中最小的元素。 理解Map Map里key集合和Set集合里元素的存储形式也很像,Map子类和Set子类在名字也惊人地相似:如Set接口下有HashSet,LinkedHashSet,SortedSet(接口),TreeSet,EnumSet等实现类和子接口,而Map接口下则有HashMap,LinkedHashMap,SortedMap(接口),TreeMap,EnumMap等实现类和子接口。正如它们名字所暗示的,Map的这些实现类和子接口中key集存储形式对应Set集合中元素的存储形式完全相同。 如果把Map所有value放在一起来看,它们又非常类似于一个List:元素与元素值可以重复,每个元素可以根据索引来查找,只是Map中的索引不再使用整数值,而是以另一对象来作为索引。如果需要从List集合中取出元素,需要提供该元素的数字索引。 HashMap和Hashtable HashMap和HashMap都是Map接口的典型实现类,它们的区别如下: -Hashtable是一个线程不安全的Map实现,但HashMap是线程不安全的实现,所以HashMap比Hashtable的性能高一点;但如果有多条线程访问同一个Map对象时,使用Hashtable实现类会更好。 -Hashtable不允许使用null作为Key和value,如果试图把null值放进Hashtable中,将会引发NullPointException异常;但HashMap可以使用null作为key或value. LinkedHashMap LinkedHashMap也使用双向链表来维护key-value对的次序,该链表定义了迭代顺序,该迭顺序与key-value对的插入顺序保持一致。 LinkedHashMap可以避免需要对HashMap,Hashtable里的Key-value对进行排序(只要插入key-value对时保持顺序即可)。同时又可避免使用TreeMap所增加的成本。 Map接口 Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,另外一组值用于保存Map里的value,另外一组用于保存Map里的value,key和value都可以是任何引用类型的数据。Map的key不允许重复,即同一个Map对象的任何两个key通过equals方法比较总是返回false. key和value之间存在单向一对一关系,即通过指定的key,总能找到唯一的,确定的value.从Map中取出数据时,只要给出指定的key,就可以取出对应的value. Properties类 Properties类是Hashtable类的子类,正如它的名字暗示的该对象在处理属性文件时特别方便(Windows操作平台上的ini文件就是一种属性文件)。Properties类可以把Map对象和属性文件关联起来,从而可以把Map对象和属性文件关联起来,从而可以把Map对象中的key-value对写入属性文件,也可以把属性文件中的属性名=属性值加载到Map对象中。由于属性文件里的属性名,属性值只能是字符串类型,所以Properties里的key,value都是字符串类型,该类提供了如下三个方法来修改Properties里的key,value值。 -String getProperty(String key):获取Properties中指定属性名对应的属性值,类似于Map的get(Object key)方法。 -String getProperty(String key ,String defaultValue):该方法与前一个方法基本相似。该方法多一个功能,如果Properties中不存在指定key时,该方法返回默认值。 -Object setProperty(String key,String value):设置属性值,类似Hashtable 的put方法。 TreeMap Map接口也派生了一个SortedMap子接口,SortedMap也有一个TreeMap实现类。 与TreeSet类似的是,TreeMap也是基于红黑树对TreeMap中所有Key进行排序,从而保证TreeMap中所有key-value对处于有序状态。TreeMap也有两种排序方式: 自然排序:TreeMap的所有key必须实现Comparable接口,而且所有key应该是同一个类的对象,否则将会抛出ClassCastException异常。 -定制排序:创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中所有key进行排序。采用定制排序时不要求Map的key实现Comparable接口。 WeakHashMap WeakHashMap与HashMap的用法基本相似。但与HashMap的区别在于,HashMap的key保留对实际对象强引用,着意味着只要该HashMap对象不被销毁,该HashMap对象所有key所引用的对象不会被垃圾回收,HashMap对象所有key所引用的对象不会被垃圾回收,HashMap也不会自动删除这些所对应的key-value对象; 但WeakHashMap的key只保留对实际对象的弱引用,这意味着如果该WeakHashMap对象所有key所引用的对象没有被其他强引用变量所引用 ,则这些key所引用的对象可能被垃圾回收,WeakHashMap也可能自动删除这些key所对应的key-value对象。 IdentityHashMap IdentityHashMap实现类的实现机制与HashMap基本相似,但它在处理两个key相等时比较独特:在IdentityHashMap中,当且仅当两个key严格相等(key1==key2)时,IdentityHashMap才认为两个建相等, 对于普通HashMap而言,只要key1和key2通过equals比较返回true,且它们的hashCode值相等即可。 EnumMap EnumMap是一个与枚举类一起使用的Map实现, EnumMap中所有key都必须是单枚举类的枚举值。创建EnumMap时必须显示或隐式指定它对应的枚举类。 EnumMap在内部以数组形式保存,所以这种实现形式非常紧凑,高效。 EnumMap根据key的自然顺序(即枚举值在枚举类中的定义顺序)来维护key-value对的次序。当程序通过keySet(),entrySet(),values()等方法来遍历EnumMap时即可看到这种顺序。 EnumMap不允许使用null作为KEY值,但允许使用null作为value.如果试图使用null作为key将抛出NullPointerException异常。如果仅仅只是查询是否包含值为null的key,或者仅仅只是使用删除值为null的key,都不会抛出异常。 HashSet和HashMap的性能 因为HashSet和HashMap,Hashtable都使用hash算法来决定其元素(对HashMap则是key)的存储,因此HashSet,HashMap的hash表包含如下属性: -容量(capacity):hash表中桶的数量。 -初始化容量(initial capacity):创建hash表时桶的数量。HashMap和HashSet都允许在构造器中指定初始化容量。 -尺寸(size):当前散列表中记录的数量。 -负载因子(load factor):负载因子等于“size/capacity".负载因子为0,表示空的hash表,0.5表示半满的散列表,依此类推。轻负载的散列表具有冲突少,适宜插入与查询的特点(但是使用Iterator迭代元素时会变慢)。 Collections Java提供了一个操作Set,List和Map等集合的工具类:Collections,该工具类里提供了大量方法对集合元素进行排序,查询和修改等操作。 Collections还提供了将集合对象设置不可变,对集合对象实现同步控制等方法。 Enumeration接口 Enumeration接口是Iterator迭代器的”古老版本“,从JDK1.0开始,Enumeratio接口就已经存在了(Iterator从JDK1.2才出现)。Enumeration接口比Iterator小,只有两个名字很长的方法: -boolean hashMoreElements():如果此迭代器还有剩下的元素返回True. -Object nextElement():返回该迭代器的下一个元素,如果还有的话(否则抛出异常)。 算法 Collection类中的静态方法 用于排序,搜索,混排和数据操纵 方法的第一个参数要执行操作的集合 重要异常: -ClassCastException -UnsupportedOperationException Class AlgoithmExample{ public static void main (String args[]){ LinkedList link= new LinkedList(); link.add(new Integer(10)); link.add(new Integer(35)); link.add(new Integer(23)); link.add(new Integer(54)); link.add(new Integer(36)); Comparator cmp = Collctions.reverseOrder(); Collections.sort(link,cmp); Iterator it =link.iterator(); System.out.println("逆序排序列表为:"); while (it.hasNext()){ System.out.println(it.next()); } System.out.println("给定列表中的最大值为:"+Collctions.max(link)); System.out.println("给定列表中的最小值为:"+Collections.min(link)); } } 集合框架的优点 提供一组可用的集合接口 提供有效的数据结构和算法 可以方便地扩展或改写集合 接口的实现都是可交换的 使设计新API的工作降到最少 接口和算法的可重用性
    Processed: 0.015, SQL: 9