java中的 集合 (一)

一、集合是什么?

  Java集合类存放于 java.util 包中,是一个用来存放对象的容器。

注意:①、集合只能存放对象。比如你存一个 int 型数据 1放入集合中,其实它是自动转换成 Integer 类后存入的,Java中每一种基本类型都有对应的引用类型。

   ②、集合存放的是多个对象的引用,对象本身还是放在堆内存中。

   ③、集合可以存放不同类型,不限数量的数据类型。

 Collection是最基本的集合接口,一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。

2、Iterable 和 Iterator 的区别

    1. 两者都是接口,Iterable位于java.lang包下,Iterator位于java.util包下,两者之间的关系是Iterable接口提供了一个获取Iterator接口实例的方法。

    2.  Iterator是迭代器,如果一个对象拥有迭代器,那么就可以将对象中的所有元素和内容遍历出来,所以所有实现了Iterable接口的所有类都拥有迭代器Iterator。

              3.  Collection 接口 继承 Iterable接口(Java集合的顶层接口)(不包括 map 系列的集合,Map接口 是 map 系列集合的顶层接口)

迭代器Iterator 的方法:

    Object next():返回迭代的下一个元素。,返回值是 Object,需要强制转换成自己需要的类型

    boolean hasNext():判断容器内是否还有可供访问的元素

    void remove():删除迭代器刚越过的元素

ListIterator相对Iterator增加了如下3个方法:

    boolean hasPrevious():返回该迭代器关联的集合是否还有上一个元素。

    Object previous():返回该迭代器的上一个元素。

    void add():在指定位置插入一个元素。

public class Test {

    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
//迭代器遍历
//遍历原理:得到迭代器-->是否有下一个元素-->如果有就返回下一个元素.    
            Iterator it = list.iterator();
            while(it.hasNext()){       //hasNext()判断是否存在下一个元素
                 Object next = it.next(); //返回迭代的下一个元素。 
                System.out.print(next);   //abcd
            }  
//       单项迭代器就是单项迭代器
            Iterator it2 = list.iterator();
            while(it2.hasNext()){ 
//      在迭代器中使用 list 直接添加或删除元素,  报 运行时修改异常  ConcurrentModificationException
                //list.add(3);   
                //list.remove("a"); 
//     但是set方法却不报错,因为指针没有移动
                //list.set(3, "我set方法却不报错,哈哈");
                System.out.print(it2.next());   //abcd
         如果:这里加入:it2.remove(); 遍历一个删一个,最后list集合里面的全没了。
} it2.remove(); // 从迭代器指向的 collection集合 中移除迭代器返回的最后一个元素 //双向迭代遍历 interface ListIterator<E> extends Iterator<E> // 双向迭代器可以从前向后迭代,同时也可以从后向前迭代, // 在API中是用ListIterator来实现的,该接口继承Iterator接口 ListIterator listIt=list.listIterator();//获得列表迭代器,扩展了Iterator接口 while(listIt.hasNext()){//向后遍历 System.out.print(listIt.next()); //abc listIt.add(" 我可以用耶 "); } System.out.println("=======下面开始反向迭代======="); while(listIt.hasPrevious())//返回该迭代器关联的集合是否还有上一个元素。 {//返回该迭代器的上一个元素。 System.out.print(listIt.previous());// 我可以用耶 c 我可以用耶 b 我可以用耶 a } } }

     

3.面试题:ArrayList和LinkedList的关系和区别?

    1.原理不一样  ArrayList基于数组,改查快, 添删慢  ;LinkedList基于链表实现,添加删除快   查询修改慢

    2.两者都是集合框架中的容器,可以存储重复的数据,都是List接口的实现类

    3.LinkedList可以用来模拟队列以及堆栈的数据结构

    4.LinkedList相对于ArrayList多了很多的方法,其实操作链表的头部和尾部的一些方法

4. Queue  [kju:]  和 Deque  ['dek]

结构:QueueDeque都是接口,Deque接口继承Queue接口,LinkedListDeque的实现类。

  1. Queue表示一种队列,也是一种数据结构,它的特点是先进先出,因此在队列这个接口里面提供了一些操作队列的方法,同时LinkedList也具有这些方法;
  2. Deque(Double ended queues双端队列),支持在两端插入或者移除元素; 那也应该具有操作双端队列的一些方法;
  3. LinkedList是他们的子类,说明都具有他们两者的方法;LinkedList也可以充当队列,双端队列,堆栈多个角色;

 5 .ArrayList类的常用方法

每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小。默认初始容量为10。随着ArrayList中元素的增加,它的容量也会不断的自动增长。在每次添加新的元素时,ArrayList都会检查是否需要进行扩容操作,扩容操作带来数据向新数组的重新拷贝,所以如果我们知道具体业务数据量,在构造ArrayList时可以给ArrayList指定一个初始容量,这样就会减少扩容时数据的拷贝问题。当然在添加大量元素前,应用程序也可以使用ensureCapacity操作来增加ArrayList实例的容量,这可以减少递增式再分配的数量。

      注意,ArrayList实现不是同步的。ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类。

        List list = Collections.synchronizedList(new ArrayList(...)); 

        ——ArrayList   线程不安全,查询速度快

  ——Vector  线程安全,但速度慢,已被ArrayList替代

  ——LinkedList  链表结果,增删速度快

package ArrayList类的常用方法;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test {
    public static void main(String[] args) {
/*构造方法:    1.    ArrayList()  构造一个初始容量为10的空列表,这是最常用的构造方法    
           2.    ArrayList(Collection<? extends E> c) 
                        构造一个包含指定 collection 的元素的列表,这些元素是按照该collection的迭代器返回它们的顺序排列的
              3.    ArrayList(int initialCapacity)  构造一个具有指定初始容量的空列表。 
*/            
/*//1. 增:  4个方法:
//        1.1     add(E e):将指定的元素添加到此列表的尾部。
//        1.2     add(int index, E element):将指定的元素插入此列表中的指定位置。
//      1.3     addAll(Collection<? extends E> c):按照指定 collection的迭代器所返回的元素顺序,
//              将该 collection中的所有元素添加到此列表的尾部。
//      1.4     addAll(int index, Collection<? extends E> c):从指定的位置开始,将指定 collection 中的所有元素插入到此列表中。     
 */
//案例:
        ArrayList list = new ArrayList();
        list.add(5);
        list.add(2);
        list.add(2, '你');//将置顶元素添加到指定位置(插入算法)
        System.out.println(list);   //[5, 2, 你]
        
        ArrayList list2 = new ArrayList();
        list2.add("13");
        list2.add("14");
        list2.add("呀");

        list.addAll(list2);
        System.out.println(list);   //[5, 2, 你, 13, 14, 呀]
        
        list.addAll(2, list2);
        System.out.println(list);  //[5, 2, 13, 14, 呀, 你, 13, 14, 呀]
        
        list.set(5, "你好呀");
        System.out.println(list);  //[5, 2, 13, 14, 呀, 你好呀, 13, 14, 呀]

/* 2. 删:   4个方法:
//        2.1        clear()  移除此列表中的所有元素。 
//        2.2     remove(int index):移除此列表中指定位置上的元素。
//        2.3     remove(Object o):移除此列表中首次出现的指定元素(如果存在)。
//         2.4        removeAll():移除此 collection 中那些也包含在指定 collection 中的所有元素
 */
//    案例:
        list.remove(2);
        list.remove("14");
        System.out.println(list);  // [5, 2, 呀, 你好呀, 13, 14, 呀]
    
        list.removeAll(list2);
        System.out.println(list);  //[5, 2, 你好呀]
        list.clear();
        System.out.println(list);  //[]
        
/*3. 改:
          3.1     set(int index, E element):用指定的元素替代此列表中指定位置上的元素。
          3.2     ensureCapacity(int minCapacity) 增加此 ArrayList 实例的容量,手动扩容
          3.3     trimToSize()  将此 ArrayList 实例的容量调整为列表的当前大小 .
                               比如最开始容器大小为100,后来发现容器只添加了5个,就可以使用该方法,调整为只有5个元素的容器
*/    //案例:    
        ArrayList list3 = new ArrayList(50);
        list3.add("你好");
        list3.add("我好");
        list3.add("大家好");
        list3.set(2, "enen");
        System.out.println(list3);  //[你好, 我好, enen]
        list3.ensureCapacity(40);
        System.out.println(list3.size());   //3
        list3.trimToSize();
/*4. 查:    
           4.1     size()  返回此列表中的元素数。
          4.2    get(int index)  返回此列表中指定位置上的元素 
         4.3    indexOf(Object o)  返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 -1
         4.4     lastIndexOf(Object o)  返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 -1。
 */    
        System.out.println(list3.get(1));            //我好
        System.out.println(list3.indexOf("我好")); //1
        
/*5. 其他方法
 */        System.out.println(list.isEmpty());           //true
         System.out.println(list3.contains("我好"));  //true
//           Object[] toArray()  按适当顺序(从第一个到最后一个元素)返回包含此列表中所有元素的数组 
         System.out.println(Arrays.toString(list3.toArray())); //[你好, 我好, enen]
    }

}

 6.LinkedList类的常用方法

 首先我们先看LinkedList的定义:

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

      从这段代码中我们可以清晰地看出LinkedList继承AbstractSequentialList,实现List、Deque、Cloneable、Serializable。其中AbstractSequentialList提供了 List 接口的骨干实现,从而最大限度地减少了实现受“连续访问”数据存储(如链接列表)支持的此接口所需的工作,从而以减少实现List接口的复杂度。Deque一个线性 collection,支持在两端插入和移除元素,定义了双端队列的操作。

package LinkedList类的常用方法;

import java.util.AbstractSequentialList;
import java.util.Deque;
import java.util.List;

public class Test {
    public static void main(String[] args) {
// LinkedList<E>  extends AbstractSequentialList<E>
//        implements List<E>, Deque<E>, Cloneable, java.io.Serializable
    
//1. 构造方法: 
/*    1.1  LinkedList()空参构造,仅仅只是将header节点的前一个元素、后一个元素都指向自身。
        public LinkedList() {
            header.next = header.previous = header;
        }
        
    1.2     LinkedList(Collection<? extends E> c)   
        构造一个包含指定 collection 中的元素的列表,这些元素按其 collection 的迭代器返回的顺序排列。
        public LinkedList(Collection<? extends E> c) {
            this();
            addAll(c);
        }
*/
//2. 两个字段  :    size表示的LinkedList的大小,header表示链表的表头
        //Entry为节点对象。
/*        private transient Entry<E> header = new Entry<E>(null, null, null);
        private transient int size = 0;
*/        
        
//3. 常用方法 LinkedList的方法和ArrayList差不多,因为他们都实现了List接口,在List接口中已经定义了大部分的共有方法,
//由于LinkedList使用的数据结构是链表方式,所以在有些方法上有些差别,差别在于可以在容器的头部和尾部对元素做操作:

 下面介绍LinkedList实现Deque接口的方法

public class Test {
    public static void main(String[] args) {
        Deque<Integer> deq = new LinkedList();
        deq.add(1);
        deq.add(2);
        deq.add(3);
        deq.add(4);
        deq.add(5);
        System.out.println(deq);  // [1, 2, 3, 4, 5]
//1. peek()和element()方法 都是获取(不移除此双端队列)队列的头部
//        区别:peek(),如果链表为空,则返回null。element(),如果链表为空,则抛异常。
        System.out.println(deq.peek());          //  1
        System.out.println(deq.element());        // 1
        
//2.  peekFirst() 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。
//      peekLast()  获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。 
        System.out.println(deq.peekFirst());    //1
        System.out.println(deq.peekLast());     //5
        
//3. poll()   pop() 获取并移除此列表的头(第一个元素)     pop()出栈      push压栈
//        poll()和 pop()区别:  如果此列表为空,pop()抛出NoSuchElementException,poll()则返回 null
        System.out.println(deq.poll());         //1
        System.out.println(deq);                //[2, 3, 4, 5]
        System.out.println(deq.pop());          //2
        System.out.println(deq);                //[3, 4, 5]
        
//4.  pollFirst()  获取并移除此列表的第一个元素;如果此列表为空,则返回 null。 
//      pollLast()  获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。 
        System.out.println(deq.pollFirst());    //3
        System.out.println(deq.pollLast());     //5
        
//5   push(E e)   将元素推入此列表所表示的堆栈 ,
//            如果成功,则返回 true,如果当前没有可用空间,则抛出 IllegalStateException。
        deq.push(520131);
        System.out.println(deq);  //[520131, 4]
    }
}

7.HashSet类的常用方法

HashSet堪称查询速度最快的集合,因为其内部是以HashCode来实现的。

它内部元素的顺序是由哈希码来决定的,所以它不保证set 的迭代顺序;特别是它不保证该顺序恒久不变。

package HashSet类的常用方法;

import java.util.AbstractSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Test3 {
    public static void main(String[] args) {
//继承关系: class HashSet<E> extends AbstractSet<E>  implements Set<E>, Cloneable, java.io.Serializable
        
        
/*1. 字段
        //基于HashMap实现,底层使用HashMap保存所有元素
        private transient HashMap<E,Object> map;

        //定义一个Object对象作为HashMap的value
        private static final Object PRESENT = new Object();
*/
        
/*2. 构造方法
        2.1//初始化一个空的HashMap,并使用默认初始容量为16和加载因子0.75。
        public HashSet() {
            map = new HashMap<>();
        }
        
         2.2// 构造一个包含指定 collection 中的元素的新 set。
        public HashSet(Collection<? extends E> c) {
            map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
            addAll(c);
        }
        
        
         2.3//构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和指定的加载因子
        public HashSet(int initialCapacity, float loadFactor) {
            map = new HashMap<>(initialCapacity, loadFactor);
        }
           
        
         2.4//构造一个新的空 set,其底层 HashMap 实例具有指定的初始容量和默认的加载因子(0.75)。
        public HashSet(int initialCapacity) {
           map = new HashMap<>(initialCapacity);
        }
           
        
        2.5 在API中我没有看到这个构造函数,今天看源码才发现(原来访问权限为包权限,不对外公开的)
         * 以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。
         * dummy 为标识 该构造函数主要作用是对LinkedHashSet起到一个支持作用
       HashSet(int initialCapacity, float loadFactor, boolean dummy) {
            map = new LinkedHashMap<>(initialCapacity, loadFactor);
        }
*/
/*3.普通方法
 *     前言:HashSet的方法和ArrayList的方法大同小异,差别在于:
        HashSet是无序的,所以涉及到index索引的方法在HashSet里面都没有. 
*/        
        HashSet set1 = new HashSet();
        HashSet set2 = new HashSet();
        for (int i = 0; i < 4; i++) {
            set1.add(i);   //[0, 1, 2, 3]
        }
        for (int i = 2; i < 6; i++) {
            set2.add(i);   //[2, 3, 4, 5]
        }
        set1.add(set2);
        System.out.println(set1);   //[0, 1, 2, 3, [2, 3, 4, 5]]
        set1.addAll(set2);
        System.out.println(set1);   //[0, 1, 2, 3, 4, 5, [2, 3, 4, 5]]
//迭代器遍历        
        Iterator iterator = set1.iterator();
        while(iterator.hasNext()){
            Object next = iterator.next();
            System.out.print(next);  //012345[2, 3, 4, 5]
        }
        System.out.println(set1.contains(3)); //true
        set1.remove(set2);
        System.out.println(set1); //[0, 1, 2, 3, 4, 5]
        set1.clear();
        System.out.println(set1); //[]
    }

}

8.TreeSet类的常用方法

TreeSet中默认要求里面的元素进行自然排序,强制要求里面的所有元素必须按照Comparable中的compareTo方法进行比较,如果容器里面的对象不具备compareTo方法此时就会抛出异常报错。

所以必须要让容器中的元素实现Comparable接口,这样它才具备compareTo方法。

1.TreeSet实例在调用add方法时会调用容器对象的compareTo方法对元素进行比较

2.TreeSet实例中对象必须是实现了Comparable接口

package TreeSet类的常用方法;

public class Test4 {
    public static void main(String[] args) {
//1.继承关系
/*        public class TreeSet<E> extends AbstractSet<E>
        implements NavigableSet<E>, Cloneable, java.io.Serializable
*/
//2.变量
/*        private transient NavigableMap<E,Object> m;
        
        //PRESENT会被当做Map的value与key构建成键值对
         private static final Object PRESENT = new Object();
*/
//3.构造方法
/*        //3.1默认构造方法,根据其元素的自然顺序进行排序
        public TreeSet() {
            this(new TreeMap<E,Object>());
        }
        
        //3.2构造一个包含指定 collection 元素的新 TreeSet,它按照其元素的自然顺序进行排序。
        public TreeSet(Comparator<? super E> comparator) {
                this(new TreeMap<>(comparator));
        }
        
        //3.3构造一个新的空 TreeSet,它根据指定比较器进行排序。
        public TreeSet(Collection<? extends E> c) {
            this();
            addAll(c);
        }
        
        //3.4构造一个与指定有序 set 具有相同映射关系和相同排序的新 TreeSet。
        public TreeSet(SortedSet<E> s) {
            this(s.comparator());
            addAll(s);
        }
        //3.5
        TreeSet(NavigableMap<E,Object> m) {
            this.m = m;
        }
*/
//4.主要方法
/*        1、add:将指定的元素添加到此 set(如果该元素尚未存在于 set 中)。

        public boolean add(E e) {
                return m.put(e, PRESENT)==null;
            }
        2、addAll:将指定 collection 中的所有元素添加到此 set 中。

        public  boolean addAll(Collection<? extends E> c) {
                // Use linear-time version if applicable
                if (m.size()==0 && c.size() > 0 &&
                    c instanceof SortedSet &&
                    m instanceof TreeMap) {
                    SortedSet<? extends E> set = (SortedSet<? extends E>) c;
                    TreeMap<E,Object> map = (TreeMap<E, Object>) m;
                    Comparator<? super E> cc = (Comparator<? super E>) set.comparator();
                    Comparator<? super E> mc = map.comparator();
                    if (cc==mc || (cc != null && cc.equals(mc))) {
                        map.addAllForTreeSet(set, PRESENT);
                        return true;
                    }
                }
                return super.addAll(c);
            }

        3、ceiling:返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null。

        public E ceiling(E e) {
                return m.ceilingKey(e);
            }
        4、clear:移除此 set 中的所有元素。

        public void clear() {
                m.clear();
            }
        5、clone:返回 TreeSet 实例的浅表副本。属于浅拷贝。

        public Object clone() {
                TreeSet<E> clone = null;
                try {
                    clone = (TreeSet<E>) super.clone();
                } catch (CloneNotSupportedException e) {
                    throw new InternalError();
                }

                clone.m = new TreeMap<>(m);
                return clone;
            }
    
        6、comparator:返回对此 set 中的元素进行排序的比较器;如果此 set 使用其元素的自然顺序,则返回 null。

        public Comparator<? super E> comparator() {
                return m.comparator();
            }
        7、contains:如果此 set 包含指定的元素,则返回 true。

        public boolean contains(Object o) {
                return m.containsKey(o);
            }
        8、descendingIterator:返回在此 set 元素上按降序进行迭代的迭代器。

        public Iterator<E> descendingIterator() {
                return m.descendingKeySet().iterator();
            }
        9、descendingSet:返回此 set 中所包含元素的逆序视图。

        public NavigableSet<E> descendingSet() {
                return new TreeSet<>(m.descendingMap());
            }
        10、first:返回此 set 中当前第一个(最低)元素。

        public E first() {
                return m.firstKey();
            }
        11、floor:返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。

        public E floor(E e) {
                return m.floorKey(e);
            }
        12、headSet:返回此 set 的部分视图,其元素严格小于 toElement。

        public SortedSet<E> headSet(E toElement) {
                return headSet(toElement, false);
            }
        13、higher:返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 null。

        public E higher(E e) {
                return m.higherKey(e);
            }
        14、isEmpty:如果此 set 不包含任何元素,则返回 true。

        public boolean isEmpty() {
                return m.isEmpty();
            }
        15、iterator:返回在此 set 中的元素上按升序进行迭代的迭代器。

        public Iterator<E> iterator() {
                return m.navigableKeySet().iterator();
            }
        16、last:返回此 set 中当前最后一个(最高)元素。

        public E last() {
                return m.lastKey();
            }
        17、lower:返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 null。

        public E lower(E e) {
                return m.lowerKey(e);
            }
        18、pollFirst:获取并移除第一个(最低)元素;如果此 set 为空,则返回 null。

        public E pollFirst() {
                Map.Entry<E,?> e = m.pollFirstEntry();
                return (e == null) ? null : e.getKey();
            }
        19、pollLast:获取并移除最后一个(最高)元素;如果此 set 为空,则返回 null。

        public E pollLast() {
                Map.Entry<E,?> e = m.pollLastEntry();
                return (e == null) ? null : e.getKey();
            }
        20、remove:将指定的元素从 set 中移除(如果该元素存在于此 set 中)。

        public boolean remove(Object o) {
                return m.remove(o)==PRESENT;
            }
        21、size:返回 set 中的元素数(set 的容量)。

        public int size() {
                return m.size();
            }
        22、subSet:返回此 set 的部分视图

             返回此 set 的部分视图,其元素范围从 fromElement 到 toElement。
             
             public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
                     E toElement,   boolean toInclusive) {
                     return new TreeSet<>(m.subMap(fromElement, fromInclusive,
                          toElement,   toInclusive));
             }
             
              //返回此 set 的部分视图,其元素从 fromElement(包括)到 toElement(不包括)。
        
             public SortedSet<E> subSet(E fromElement, E toElement) {
                 return subSet(fromElement, true, toElement, false);
             }

        23、tailSet:返回此 set 的部分视图

               返回此 set 的部分视图,其元素大于(或等于,如果 inclusive 为 true)fromElement。
        
            public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
                return new TreeSet<>(m.tailMap(fromElement, inclusive));
            }
            
            //返回此 set 的部分视图,其元素大于等于 fromElement。
           
            public SortedSet<E> tailSet(E fromElement) {
                return tailSet(fromElement, true);
            }
*/
    }
}

部分内容参考别人的作品: https://www.cnblogs.com/chenssy/

原文地址:https://www.cnblogs.com/gshao/p/10116891.html