概念

  • 当我们要保存一组一样的元素的时候,我们需要用一个容器来存储,数组就是这样的容器

  • 然而数组一旦被定义,那么他的长度将不会在变化

  • 然而在我们的生活以及开发实践中,很多东西并不是一直不变的,所以这个时候就需要可以根据我们所需要的容量的容器,也就是动态增长的容器,这个时候我们就需要集合

集合API

java的集合框架里有很多接口、抽象类、具体类,都位于java.util包中

 

Collection接口

  • Collection接口中定义了存取一组对象的方法,子接口Set和List分别定义了不同的存储方式

  • List中的数据对象有顺序且可以重复

  • Set中的数据对象没有顺序且不可以重复

Collection

我们先来看一下Collection这个接口

  • Collection<E>集合可以使用泛型传入一个参数,如果不传入参数,那么默认是Object,都必须存储引用类型

              Collection c = new ArrayList();           
                         c.add("a");          
                         c.add(1);//自动装箱为包装类型         
                         c.add(true);

以上代码我们可以看出,如果不使用泛型传入一个参数的话,Collection就默认是Object,那么这个集合就不是那么精确了,这个集合我们就可以传入任何类型

            
 Collection<String> c = new ArrayList<String>();                                             c.add("a");                   
                                c.add("b");               
                                c.add("c");                
                                c.add("d");                 
                                c.add("a");                 
                          //c.clear();//清空集合中的元素              
                         //c.remove("a");//删除集合中的指定的第一次出现的元素                  System.out.println(c.contains("a"));//是否包含指定元素                      System.out.println(c.isEmpty());//集合是否为空                            System.out.println(c.size());//集合的长度                                  System.out.println(c);           
                 Object[] objs1 = c.toArray();//集合转数组                                  System.out.println(Arrays.toString(objs1));  
​
String[] objs2 = c.toArray(new String[c.size()]);//集合转数组,指定集合类型
​
Collection<String> c1 = new ArrayList<String>();
                           c1.add("a");
                           c1.add("b");
                           c1.add("c");
                           c1.add("d");
​
                 //c.addAll(c1);//将c1中的全部元素加到c中
                 //c.removeAll(c1);//删除c1在c中的内容
        //System.out.println(c.containsAll(c1));//c中包含了c1中的全部元素则返回true
        System.out.println(c.retainAll(c1));//只保留c和c1中相交的部分,没有区别的情况下返回false
        System.out.println(c);
        System.out.println(c1);
  • 当我们给Collection的泛型里传入一个参数的时候,这个集合就变得很精确了,比如Collection<String>那么这个集合表示的就是String类型,那么往里面添加元素也就只能传入String类型的值

  • 同时我们可以用Collection里的方法,详情可以参照API里的各种方法

ArrayList类

  • ArrayList类是List接口中的类之一

  • 该类实现了长度可变的数组,在内存中分配连续的存储空间

  • 遍历元素比较快,也就是查询快,由于其底层实现是数组结构,所以增删慢

//ArrayList<>()创建一个长度为10的底层数组,第一次添加元素时,真正创建数组
//ArrayList<String> alist = new ArrayList<>();
           ArrayList<String> alist = new ArrayList<>(20);                                            alist.add("a");                  
                             alist.add("b");                
                             alist.add("c");                 
                           //alist.add(0,"d");//向指定的位置插入数据
   //System.out.println(alist.get(2));//return (E) elementData(index);
   //System.out.println(alist.indexOf("b"));//找到该元素的位置
   //System.out.println(alist.remove(1));//删除并返回该位置元素                                          alist.set(1, "B");//替换指定位置的元素                                   System.out.println(alist);
   
   //ArrayList<>()创建一个长度为10的底层数组,第一次添加元素时,真正创建数组
        //ArrayList<String> alist = new ArrayList<>(20);
        /*
          add()添加一个元素到集合中的一个过程
          调用add()添加元素时,先检查底层数组是否还能放的下,如果可以,直接将元素添加到末尾,
               如果不可以,会创建一个新的数组,将原来的数组内容复制过去
                    size   --->记录实际装入数组的元素个数
                    public boolean add(E e) {
                         ensureCapacityInternal(size + 1);  //检查元素能否放得进去
                         elementData[size++] = e;
                         return true;
                         }
                            放进去后容量大小 - 底层数组长度>0
                         if (minCapacity - elementData.length > 0)
                                  grow(minCapacity);扩容
​
                                private void grow(int minCapacity) {
                                    // overflow-conscious code
                            int oldCapacity = elementData.length;
     int newCapacity = oldCapacity + (oldCapacity >> 1);新数组为原来的1.5倍
                                    if (newCapacity - minCapacity < 0)
                                        newCapacity = minCapacity;
                               if (newCapacity - MAX_ARRAY_SIZE > 0)
                          newCapacity = hugeCapacity(minCapacity);
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);数组复制,创建一个新数组,将原来的数组内容复制到新数组中
                                     }
         */
        ArrayList<String> alist = new ArrayList<>();
                          alist.add("a");
                          alist.add("b");
                          alist.add("c");
                          alist.add("c");
                          alist.add("c");
                          alist.add("c");
                          alist.add("c");
                          alist.add("c");
                          alist.add("c");
                          alist.add("c");
                          alist.add("c");
                          alist.add("c");
                          alist.add("c");
                          alist.add("c");
  • 输出的顺序是按照添加的顺序排列

  • ArrayList默认创造一个底层为长度为10的数组,如果超过这个长度,会自动扩容,扩容的新数组为原来的1.5倍

  • 长度不够的情况下,创建的新数组会将原来数组中的内容复制过去并加入新的元素

匿名内部类

           
ArrayList<String> alist = new ArrayList<>();                                              alist.add("c");                  
                             alist.add("b");                                                          alist.add("a");                
                             alist.add("d");              
                     //new 接口(){方法重写} 创建了一个匿名内部类对象           
                       /*alist.sort(new Comparator<String>() {           
                         @Override                 
                       public int compare(String o1, String o2) {       
                      return o1.compareTo(o2);                
                           }      
                              });*/            
                  //创建一个自定义String比较器类的对象              
                    //alist.sort(new StringComparator());       
         alist.sort((String o1,String o2)->{return o1.compareTo(o2);});                      System.out.println(alist);
   
   //创建的自定义的String比较器类的对象
    import java.util.Comparator;
    public class StringComparator implements Comparator<String> {
     @Override
     public int compare(String o1, String o2) {
        return o1.compareTo(o2);
     }
 }
  • 匿名内部类这个概念我们只需知道有这么个东西,后面会加深理解

  • 且匿名内部类写起来过去繁琐,后面学到的lambda表达式是对其的简洁表示

  • 形如:alist.sort((String o1,String o2)->{return o1.compareTo(o2);});

LinkedList类

  • LinkedList是List接口中的一个实现类

  • 该类采用链表存储方式。查询遍历较慢,插入、删除时效率较高

  • 添加元素时,先判断Node结点是否为空,如果为空,就可以直接添加一个新元素,如果不为空,则会创建一个新的Node添加到下一位

/*     存储重复元素      
add() 每添加一个元素创建一个Node对象       
E item;           
Node<E> next;       
Node<E> prev;     */  
                   LinkedList<String> llist = new LinkedList();                                          llist.add("a");                   
                                 llist.add("b");                   
                                 llist.add("c");                   
                                 llist.add("d");               
                                 llist.add("a");                     
                     //index<size/2从头结点开始向后找,否则从尾结点向前找                                     System.out.println(llist.get(3));                                       System.out.println(llist);}
  • 输出的顺序是按照添加元素的顺序输出

  • 因为LinkedList是双向链表,如果index<size/2就会从头找,反之,从尾结点开始找

  • 所以LinkedList的增删效果块,查询效果慢

Vector类

/*Vector底层也是数组实现,但是是线程安全的   
public synchronized boolean add(E e) {   
modCount++;        
ensureCapacityHelper(elementCount + 1);        elementData[elementCount++] = e;     
return true;}     */ 
                 Vector<String> v = new Vector<>();            
                                v.add("a");               
                                v.add("a");             
                                v.add("a");              
                                v.add("c");                
                                v.add("b");              
                                v.add("d");                 
                                v.add("f");                
                                v.add("a");                  
                                v.add("a");    
                          System.out.println(v);

Vector底层也是数组实现,不过是线程安全的,不做强调

Iterator接口

  • 是集合的迭代器,可用来遍历集合

  • 迭代器允许调用者在迭代期间从底层集合中删除元素

ListIterator类

  • 可接Iterator接口

ArrayList<String> alist = new ArrayList<>();                                             alist.add("a");                
                  alist.add("b");               
                  alist.add("c");                
                  alist.add("d");
                  alist.add("a");
                  alist.add("a");
                  alist.add("a");
                  alist.add("b");
                  alist.add("c");
/*  
for 
*/       
    /*for (int i=0;i<alist.size();i++){                                      System.out.println(alist.get(i));           
    }*/
​
/* 增强for循环 */          
       /*for(String s:alist){           
         System.out.println(s);          
         }*/
​
/* 通过迭代器 */           
/*Iterator<String> it = alist.iterator();//返回一个迭代器对象,控制元素的遍历                 while (it.hasNext()){               
                   String s =it.next();                                                 System.out.println(s);                          
                   }*/ 
​
/*ListIterator<String> lit = alist.listIterator();                                           while (lit.hasNext()){                                               System.out.println(lit.next());                                           }*/
​
//listIterator() 只能对List接口下的实现类进行遍历                         ListIterator<String> lit = alist.listIterator(alist.size());                               while (lit.hasPrevious()){                                               System.out.println(lit.previous());
​
 Iterator<String> it = alist.iterator();//返回一个迭代器对象,控制元素的遍历
                         while (it.hasNext()){
                           String s =it.next();
                              if (s.equals("a")){
                                  it.remove();//使用迭代器中的方法进行遍历
                              }
                           }
                            System.out.println(alist);
  • 通过迭代器我们可以删除多个相同的元素

  • 也可以从后向前访问元素

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐