关于集合

来源:互联网 发布:中铁建物业怎么样知乎 编辑:程序博客网 时间:2024/06/06 07:27
在学习集合之前,我们在之前学习过栈,队列,数组和链表;
栈在存储数据时有先进后出的特点,队列在存储数据是先进先出,数组用于存储同一类型数据,查询快,但是增删慢;链表通过一个链子把多个结点(元素)连接起来,由数据和地址组成的一个元素,
节点本身必须有一个地址值(就是下一个元素的地址值),增删快,查询慢。但为什么这里还要学习集合类呢?是因为面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,我们就需要对这多个对象进行存储。而目前为止我们学习过的可以存储多个元素的东西是数组,但是呢,数组长度固定,不能适应变化的需求,所以,Java就提供了集合类供我们使用。
集合:长度可变,只存储引用类型(可以对基本类型进行装箱操作使其成为引用类型),可以存储多种数据类型。java提供的集合类有很多种,可以满足我们的各种需要,下面蔚集合的分类:
Collection:
   List:
     ArrayList
     Vector
     LinkedList
   Set: 
     HashSet
     TreeSet
   Map:
     HashMap
     TreeMap
1.Collection的本质为接口,它是集合的顶层结构,定义了集合的共性
 成员方法:
  A:添加功能
    boolean add(Object obj):往集合中添加一个元素
     boolean addAll(Collection c):往集合中添加多个元素
    B:删除功能
     void clear():清空所有元素
     boolean remove(Object o):从集合中删除一个元素
    boolean removeAll(Collection c):从集合中删除另一个集合的元素
   C:判断功能
    boolean contains(Object o):判断集合中是否包含指定的元素
    boolean containsAll(Collection c):判断集合中是否包含另一个集合的元素
    boolean isEmpty():判断集合是否为空。
  D:交集功能
    boolean retainAll(Collection c)
   E:迭代器(集合特有的遍历方式)
   Iterator iterator()
   重点:Iterator的使用
    A:使用步骤
    B:迭代器原理
   F:长度功能
   int size():返回集合中元素的个数
  G:集合转数组
   Object[]toArray()
在学习这些方法后,我们便有两种可以遍历集合的方法,一种利用toArray()方法,另一种是利用迭代器,这是集合特有的便利方法,下列代码做一示范:
  package com.edu.collection;
  /**
   * 创建狗对象(带参数),存储到集合,用迭代器进行遍历并打印对象的属性数据
   * 1.创建狗类
   * 2.创建狗对象
   * 3.创建集合,并将狗对象添加到集合中
   * 4.创建狗集合的迭代
   * 5.利用迭代遍历狗集合
   */
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Iterator;
  public class DogInterator {
   public static void main(String[] args) {
    // 2.创建狗对象
    Dog d1 = new Dog("Bob",2);
    Dog d2 = new Dog("Kite",1);
    Dog d3 = new Dog("XiaoMing",2);
    //3.创建集合,并将狗对象添加到集合中
    Collection<Dog> c = new ArrayList<Dog>();
    
    c.add(d1);
    c.add(d2);
    c.add(d3);
    //4.创建狗集合的迭代
    Iterator<Dog> iterator = c.iterator();
    // 5.利用迭代遍历狗集合
    while(iterator.hasNext()){
     Dog d = (Dog)iterator.next();
     System.out.println(d.getName() + "  " + d.getAge());
    }
   }
  }
  
A.List   
  (1)List集合的元素有序(存储和取出顺序一致),元素可重复
  (2)List的特有功能:
   A:添加功能
   void add(int index,Object obj):在指定的位置添加元素
   B:删除功能
   Object remove(int index):通过指定的索引删除元素,并把删除的元素返回
   C:获取功能
   get(int index) 返回列表中指定位置的元素。
   D:替换功能
   Object set(int index,Object obj) 
  (3) List中元素顺序可以被洗牌Collections.shuffle(list)
   List中元素顺序可以被倒序Collections.reverse(list)
1.ArrayList
  (1)构造方法
   ·ArrayList():构造一个初始容量为 10 的空列表。
   ·ArrayList(Collection<? extends E> c):构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
   ·ArrayList(int initialCapacity):构造一个具有指定初始容量的空列表。
2.LinkedList
  (1)构造方法
    ·LinkedList()
       构造一个空列表。
    ·LinkedList(Collection<? extends E> c)
       构造一个包含指定 collection 中的元素的列表,这些元素按其 collection 的迭代器返回的顺序排列。
  (2)特有功能:
    public void addFirst(E e)
    public void addLast(E e)
    
    public E getFirst()
    public E get()
    
    public void removeFirst()
    public viod removeLast()
总结:·ArrayList和LinkedList都是List集合接口的实现类对象,集合内部元素的排序都是有序的,并且元素可重复,但是ArrayList的底层结构是数组(查询快增删慢,线程不安全,效率高)而LinkedList的底层结构是链表(查询满,增删快,线程不安全,效率高)
 ·对于集合的遍历还有一种比较高效的方法foreach语句,具体案例如下:
   public class LinkedListDemo {
   public static void main(String[] args) {
    //创建一个LinkedList的集合
    LinkedList<String> list = new LinkedList<String>();
    list.add("hello");
    list.add("world");
    list.add("java");
    list.addFirst("c++");
    list.addLast("js");
    Object removeFirst = list.removeFirst();
    Object removeLast = list.removeLast();
    System.out.println(removeFirst);
    System.out.println(removeLast);
    
    System.out.println("---------------");
    //遍历集合
    for(Object obj:list){
     System.out.println(obj);
     }
    }
   }
   
B.Set 
 (1)是一个接口,与List同一级别,它的超级接口是Collection和Iterable
 (2)方法:
    boolean add(E e)
     如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。
    boolean addAll(Collection<? extends E> c)
     如果 set 中没有指定 collection 中的所有元素,则将其添加到此 set 中(可选操作)。
       void clear()
     移除此 set 中的所有元素(可选操作)。
    boolean contains(Object o)
       如果 set 包含指定的元素,则返回 true。
    boolean containsAll(Collection<?> c)
       如果此 set 包含指定 collection 的所有元素,则返回 true。
    boolean equals(Object o)
       比较指定对象与此 set 的相等性。
    int hashCode()
       返回 set 的哈希码值。
    boolean isEmpty()
       如果 set 不包含元素,则返回 true。
    Iterator<E> iterator()
       返回在此 set 中的元素上进行迭代的迭代器。
    boolean remove(Object o)
       如果 set 中存在指定的元素,则将其移除(可选操作)。
    boolean removeAll(Collection<?> c)
       移除 set 中那些包含在指定 collection 中的元素(可选操作)。
    boolean retainAll(Collection<?> c)
       仅保留 set 中那些包含在指定 collection 中的元素(可选操作)。
    int size()
       返回 set 中的元素数(其容量)。
    Object[] toArray()
       返回一个包含 set 中所有元素的数组。
   <T> T[] toArray(T[] a)
       返回一个包含此 set 中所有元素的数组;返回数组的运行时类型是指定数组的类型。
Set的方法和List的方法比较类似,可以参考API学习。
   
1.HashSet:HashSet是Set接口的实现类,元素的顺序是无序的并且元素唯一,这一点和List集合不同。HashSet保证元素唯一的方法是,比较元素在内存中的哈希值是否相同,并且在哈希值相同的基础上比较两者的内容是否相同,如若这两者都相同,则在向集合中添加元素的动作中(boolean add(E e)),不添加重复元素,从而保证了元素的唯一性
   HashSet的底层结构是哈希表,哈希表依赖两个方法,hashCode()和equals(),如果我们有用到Hash结构的集合,就要考虑是否需要重写这两个方法了。举个例子说明一下:
    import java.util.HashSet;
    public class HashSetDemo {
     public static void main(String[] args) {
      Car car1 = new Car("红旗", 200000, "黑色");
      Car car2 = new Car("中南海", 200000, "黑色");
      Car car3 = new Car("南山", 200000, "黑色");
     
      Car car4 = new Car("红旗", 200000, "黑色");//由于Car类型重写了hashCode()和equals()
        //方法,所以可以判断出已经存在car4,将不再添加
      
      HashSet<Car> hashSet = new HashSet<Car>();
      
      hashSet.add(car1);
      hashSet.add(car2);
      hashSet.add(car3);
      hashSet.add(car4);
      
      //遍历集合
      for (Car car : hashSet) {
       System.out.println(car.toString());
      }
     }
    }
    在Car类中重写HashCode()和equals():
      //重写hashCode()和equals()方法
       public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((bread == null) ? 0 : bread.hashCode());
        result = prime * result + ((color == null) ? 0 : color.hashCode());
        result = prime * result + price;
        return result;
       }
       public boolean equals(Object obj) {
        if (this == obj)
         return true;
        if (obj == null)
         return false;
        if (getClass() != obj.getClass())
         return false;
        Car other = (Car) obj;
        if (bread == null) {
         if (other.bread != null)
          return false;
        } else if (!bread.equals(other.bread))
         return false;
        if (color == null) {
         if (other.color != null)
          return false;
        } else if (!color.equals(other.color))
         return false;
        if (price != other.price)
         return false;
        return true;
       }
2.TreeSet
  (1)关于TreeSet中的方法可以参考API
  (2)它的底层算法是二叉树算法,二叉树算法是著名的排序算法,我们可以通过创建set时提供的Comparator对存入集合的元素进行排序,或者在创建元素对象时,实现Comparable接口并重写CompareTo方法进行排序,举例说明:
  1,利用Comparator比较器
    import java.util.Comparator;
    import java.util.TreeSet;
    public class TreeSetDemo {
     public static void main(String[] args) {
      TreeSet<Car> set = new TreeSet<Car>(new Comparator<Car>(){
       public int compare(Car c1, Car c2) {
        int price = c1.getPrice()-c2.getPrice();
        int price2 = price==0?c1.getBread().compareTo(c2.getBread()):price;
        
        return price2;
       }
      });
      
      Car car1 = new Car("红旗", 220000, "黑色");
      Car car2 = new Car("中南海", 240000, "黑色");
      Car car3 = new Car("南山", 200300, "黑色");
      Car car4 = new Car("华山", 200800, "黑色");
      
      set.add(car1);
      set.add(car2);
      set.add(car3);
      set.add(car4);
      
      //遍历集合
      for (Car car : set) {
       System.out.println(car);
      }
     }
    }
  2.利用重写CompareTo方法
   在Car类中重写CompareTo
     public class Car{
      ......//省略一些
      public int compareTo(Car car) {
       int price = this.getPrice()-car.getPrice();
       int price2 = price==0?this.getBread().compareTo(car.getBread()):price;
       
       return price2;
      }
     }
     import java.util.TreeSet;
     public class ComparableDemo {
      public static void main(String[] args) {
       TreeSet<Car> set = new TreeSet<Car>();
       
       Car car1 = new Car("红旗", 220000, "黑色");
       Car car2 = new Car("中南海", 220000, "黑色");
       Car car3 = new Car("南山", 200300, "黑色");
       Car car4 = new Car("华山", 200800, "黑色");
       
       set.add(car1);
       set.add(car2);
       set.add(car3);
       set.add(car4);
       
       //遍历集合
       for (Car car : set) {
        System.out.println(car);
       }
      }
     }
总结:HashSet和TreeSet都是单列集合元素不可重复,但他们底层存储数据的结构不一样,HashSet底层用的是HashMap哈希表结构存储,而TreeSet底层用的是TreeMap树结构存储,还有就是HashSet存储无序,而TreeSet存储数据是有序的   
   
C.Map
 Map是形容java中一种一一对应的映射关系的集合,该集合一次存储两个数据一个叫键,一个叫值,键和值一一对应
 Map集合中共有的方法:
   A:删除功能
     void clear():移除集合中的所有键值对元素
     V remove(Object key):根据键移除键值对元素,并返回值
     B:判断功能
      boolean containsKey(Object key):判断集合中是否包含指定的键
      boolean containsValue(Object value):判断集合中是否包含指定的值
     boolean isEmpty():判断集合是否为空
    C:获取功能
      Set<Map.Entry<K,V>> entrySet():获取键值对对象的集合,遍历键值对对象,
    利用getKey(),getValue()取出键和值(理解即可)
      
    V get(Object key):根据键获取值
      Set<K> keySet():获取所有的键
        Collection<V> values():获取所有的值
     D:添加功能
     V put(K key,V value):集合添加键值对
     E:长度功能
     int size():键值对对数。
1.HashMap 
  HashMap是底层算法为Hash算法的一种Map接口实现类,对元素的顺序不可预测,相对于TreeMap来说它对键值没有要求,需要注意的是,当键值为引用类型的时候,我们需要重写引用类型的hashCode()和equals()方法,因为它的底层算法为hash算法,我们在判断是否元素是否重复是要用到,重写的方法同HashSet相同。4
2.TreeMap
  元素顺序:元素顺序与键的排序规则有关 
  底层算法:Tree算法 
总结:相同点:主要用于存储键(key)值(value)对,根据键得到值,因此键不允许键重复,但允许    值重复。
   不同点:      
    1.HashMap里面存入的键值对在取出的时候是随机的,也是我们最常用的一个Map.根据键可以直接获取它的值,
    具有很快的访问速度。在Map 中插入、删除和定位元素,HashMap 是最好的选择。 
    2.TreeMap取出来的是排序后的键值对。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。   
D.关于泛型  
   泛型是一种把明确数据类型的工作放在运用此数据是在做的特殊类型,这样做避免了强制类型转换,优化程序设计,把运行时期问题提前到了编译时期,泛型可用于类,方法,接口。
   
0 0