黑马程序员11--集合

集合

------- android培训java培训、期待与您交流! ----------

集合类只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。
黑马程序员--集合 - leon_hm - Leon的博客

Collection
   |-- List
  |-- ArrayList:底层的数据结构是数组结构。查询很快。但是增删稍慢。线程不同步。
  |-- LinkedList:底层使用的链表结构。查询慢,增删快。
  |-- Vector:底层是数组数据结构。线程同步。被ArrayList替代了。
 
|-- Set:元素无序(存入和取出的顺序不一定一致),元素不可以重复
|-- HashSet 底层结构是哈希表
       HashSet通过元素的两个方法,hashCode和equals来完成。
       如果元素的hashCode值相同,才会判断equals是否为true.
        如果元素的hashCode值不同,不会调用equals。
        注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。     
          |--TreeSet:可以对Set集合中的元素进行排序
              底层数据结构是二叉树。
              保证元素唯一性的依据。
              compareTo方法return 0;
              
              TreeSet排序的第一种方式:让元素自身具备比较性
              元素需要实现Comparable接口,覆盖compareTo方法
              这种方式也称为元素的自然顺序,或者叫做默认顺序。
  
              TreeSet的第二种排序方式:
              当元素自身不具备比较性时,或者具备的比较性不是所需要的。
              这时就需要集合自身具备比较性。
              在集合初始化时,就有了比较方式。

 List 集合特有的迭代器。ListIterator是Iterator的子接口
 
 在迭代时,不可以通过集合对象的方法操作集合中的元素
 因为会发生ConcurrentModificationException异常。
 
 所以,在迭代时,只能用迭代器的方式操作元素,可是Iterator方法是有限的,
 只能对元素进行判断,取出,删除的操作
 如果想要其他的操作如添加,修改等,就需要使用其子接口ListIterator
 
 该接口只能通过List集合的listIterator方法获取

ArrayList
凡是可以操作角标的方法都是List所特有的。
add(element)
add(index,element);
addAll(index,Collection);

删除
remove(Object)
remove(index)

clear() // 清空

set(index,element)

get(index)
subList(from,to)
listIterator();

获取个数
size()
判断是否包含元素
contains(元素)
判断是否为空
isEmpty();

        ArrayList al  =  new ArrayList();
        
         //添加元素
        al.add( "java01");
        al.add( "java02");
        al.add( "java03");
        al.add( "java04");
        
         //在特定位置添加
        al.add( 1, "java09");
        
         //获取个数,集合长度
        System.out.println( "size:" +al.size());
        
         //删除元素
        al.remove( "java02");
        al.clear(); //清空集合
        
         //判断是否包含元素
        al.contains( "java3");
         //判断是否为空
        al.isEmpty();
        
         //按数组的方式迭代
         for ( int i = 0;i <al.size();i ++)
        {
            System.out.println( "al(" +i + ")=" +al.get(i));
        }
        
         //Iterator迭代
         for(Iterator it =al.iterator();it.hasNext();)
        {
            System.out.println(it.next());
        }
            
        System.out.println(al.indexOf( "java02"));
        
        List sub  = al.subList( 1, 3);
        
        System.out.println( "sub=" +sub);
        
        Iterator it = al.iterator(); //获取迭代器,用于取出集合中的元素
         while(it.hasNext())
        {
             System.out.println(it.next());    
        }

Vector
Vector特有的迭代方式,枚举
枚举和迭代是一样的
因为枚举的名称和方法的名称都过长
所以被迭代器取代了。

        Vector v  =  new Vector();
        
        v.add( "java01");
        v.add( "java02");
        v.add( "java03");
        v.add( "java04");
        
         //枚举
        Enumeration en = v.elements();
        
         while(en.hasMoreElements())
        {
            System.out.println(en.nextElement());
        }


LinkedList
特有方法:
addFirst()
addLast()

getFirst()
getLast()
获取元素,但不删除元素,如果集合中没有元素,则会出现NoSuch ElementException

removeFirst()
removeLast()
获取元素,但是元素被删除,如果集合中没有元素,会出现 NoSuch ElementException

在JDK1.6出现了替代方法
offerFirst()
offerLast()

peekFirst();
peekLast();
获取元素,但不删除元素,如果集合中没有元素, 会返回null

pollFirst();
pollLast();
获取元素,但是元素被删除,如果集合中没有元素,会返回null

        LinkedList ll  =  new LinkedList();
        
         //从最前面添加
        ll.addFirst( "java01");
        ll.addFirst( "java02");
        ll.addFirst( "java03");
        ll.addFirst( "java04");
         //从最后面添加
        ll.addLast( "java01");
        ll.addLast( "java02");
        ll.addLast( "java03");
        ll.addLast( "java04");
         //获取第一个
        System.out.println(ll.getFirst());
         //获取最后一个
        System.out.println(ll.getLast());
         //删除第一个
        System.out.println(ll.removeFirst());
         //获取大小
        System.out.println(ll.size());
        
         while ( !ll.isEmpty()) {
            System.out.println(ll.removeFirst());
        }
         while ( !ll.isEmpty()) {
            System.out.println(ll.removeLast());
        }

HashSet
HashSet通过元素的两个方法,hashCode和equals来完成。
如果元素的hashCode值相同,才会判断equals是否为true.
如果元素的hashCode值不同,不会调用equals。
注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。
class Person1
{
     private String name;
     private  int age;
    Person1(String name, int age)
    {
         this.name =name;
         this.age =age;
    }    
    
     public String getName()
    {
         return name;    
    }
    
     public  int getAge()
    {
         return age;    
    }
    
     //覆盖Object的hashCode方法
     public  int hashCode()
    {
         return name.hashCode() +age;
    }
    
     //覆盖Object的equals方法
     public  boolean equals(Object obj)
    {
          if(obj  instanceof Person1)
         { 
             Person1 p = (Person1)obj;
              //System.out.println(this.name+" equals "+p.name);
              return p.name.equals( this.name)  && p.age == this.age;
        }
          else
          return false;
    }
}
public  class HashSetDemo {
     public  static  void main(String[] args) {
        HashSet hs  =  new HashSet();
        hs.add( new Person1( "a1", 11));    
        hs.add( new Person1( "a1", 12));    
        hs.add( new Person1( "a1", 13));    
        hs.add( new Person1( "a1", 14));    
        hs.add( new Person1( "a1", 11));    
        
        System.out.println( "a1:" +hs.contains( new Person1( "a1", 11)));
        
        hs.remove( new Person1( "a1", 11));
        
        Iterator i  = hs.iterator();
         while(i.hasNext())
        {
            Person1 p  =(Person1)i.next();
            System.out.println(p.getName() + ":" +p.getAge());
        }
    }
}

TreeSet
可以对Set集合中的元素进行排序
底层数据结构是二叉树。
保证元素唯一性的依据。
compareTo方法return 0;
TreeSet排序的第一种方式:让元素自身具备比较性
                                        元素需要实现Comparable接口,覆盖compareTo方法
                                        这种方式也称为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式:
                                       当元素自身不具备比较性时,或者具备的比较性不是所需要的。
                                      这时就需要集合自身具备比较性。
                                      在集合初始化时,就有了比较方式。
                                               定义一个类,实现Comparator接口,覆盖compare方法

当两种排序方式都存在时,以第二种方式为主。

方式一:
public  class TreeSetDemo {
     public  static  void main(String[] args) {
        TreeSet ts  =  new TreeSet();
        ts.add( new Student( "lisi01"22));
        ts.add( new Student( "lisi007"20));
        ts.add( new Student( "lisi09"19));
        ts.add( new Student( "lisi01"40));
        ts.add( new Student( "lisi01"19));
        Iterator it  = ts.iterator();
         while (it.hasNext()) {
            Student s  = (Student) it.next();
            System.out.println(s.getName()  +  ":"  + s.getAge());
        }
    }
}
class Student  implements Comparable  // 该接口强制让学生具备比较性
{
     private String name;
     private  int age;
    Student(String name,  int age) {
         this.name  = name;
         this.age  = age;
    }
     public String getName() {
         return name;
    }
     public  int getAge() {
         return age;
    }
     public  int compareTo(Object o) {
         if ( !(o  instanceof Student))
             throw  new RuntimeException( "不是学生对象");
        Student s  = (Student) o;
         if ( this.age  > s.age)
             return  1;
         else  if ( this.age  == s.age) {
             return  this.name.compareTo(s.name);
        }  else
             return  - 1;
    }
}

方式二:
class Student2   implements Comparable
{
    String name;
     int age;
     public Student2(String name,  int age) {
         this.name  = name;
         this.age  = age;
    }
     public String getName() {
         return name;
    }
     public  int getAge() {
         return age;
    }
     //自然顺序 先比较年龄再比较姓名
      public  int compareTo(Object obj)
     {
          if( !(obj  instanceof Student2))
          throw  new RuntimeException( "not Student object");
    
         Student2 s =(Student2)obj;
    
          if( this.age >s.age)
          return  1;
          else  if ( this.age ==s.age)
         {
              return  this.name.compareTo(s.name);
         }
          else
         {
              return  - 1;
         }
     }
}
class TreeSetDemo2 {
     public  static  void main(String[] args) {
        TreeSet ts  =  new TreeSet( new MyCompare()); //传入比较器,按照自定义的方式比较
        ts.add( new Student2( "lisi01"22));
        ts.add( new Student2( "lisi007"20));
        ts.add( new Student2( "lisi09"19));
        ts.add( new Student2( "lisi01"40));
        ts.add( new Student2( "lisi01"19));
        Iterator it  = ts.iterator();
         while (it.hasNext()) {
            Student2 s  = (Student2) it.next();
            System.out.println(s.getName()  +  ":"  + s.getAge());
        }
    }
}
//自定义的新比较顺序, 先比较姓名再比较年龄
class MyCompare  implements Comparator {
     public  int compare(Object o1, Object o2) {
        Student2 s1  = (Student2) o1;
        Student2 s2  = (Student2) o2;
         int num  = s1.getName().compareTo(s2.getName());
         if (num  ==  0) {
             return s1.getAge()  - s2.getAge();
        }
         return num;
    }
}

Map

Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。
   1.添加。
      put(K key,V value)
      putAll(Map<? extends K,? extends V>)
   2.删除。
      clear()
      remove(Object Key)
   3.判断。
      containsKey(Object key)
       containsValue(Object value)
       isEmpty()
   4.获取。
     get()
       size()
       values()
 
       entrySet()
       keySet()
 
Map
   |--Hashtable:底层是哈希表数据结构,不可以存入null键null值的情况。该集合线程同步的。jdk1.0 效率低
   |--HashMap:底层是哈希表数据结构。允许存入null键null值,该集合线程不同步。jdk1.2 效率高
   |--TreeMap:底层是二叉树数据结构,线程不同步。可以用于给map集合中的键进行排序
   
和Set很像
其实大家,set底层就是使用了Map集合。
class  MapDemo
{
     public  static  void main(String[] args) 
    {
        Map <String,String >  map = new HashMap <String,String >();

         //添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有键对应的值
         //并且put方法会返回覆盖的值
        System.out.println( "put:" + map.put( "01", "zhangsan01"));
        System.out.println( "put:" + map.put( "01", "lisi01"));

        map.put( "02", "zhangsan02");
        map.put( "03", "zhangsan03");

        System.out.println( "containsKey:" + map.containsKey( "012"));
        System.out.println( "remove:" + map.remove( "03"));
        System.out.println( "get:" + map.get( "02"));

        map.put( "04",null);
        System.out.println( "get:" + map.get( "04"));
         //可以通过get方法的返回值来判断一个键是否存在。
         //通过返回空来判断

        Collection <String > col  = map.values();

        System.out.println(col);

        System.out.println(map);
    }
}

map集合的两种取出方式
1.keySet:将map中所有的键存入到Set集合。因为Set具备迭代器。
         所以可以迭代方式取出所有的键,再根据get方法。获取每一个键对应的值
         Map集合的取出原理:将map集合转成Set集合。再通过迭代器出去。
2.Set<Map.Entry<k,v>> entrySet():将map集合中的映射关系存入到Set集合中,
         而这个关系的数据类型就是:Map.Entry


Map.Entry 其实Entry也是一个接口,它是Map接口中的内部接口。

interface Map
{
public static interface Entry
{
public abstract Object getKey();
public abstract Object getValue();
}
}

class HashMap implements Map.Entry
{
class Haha implements Map.Entry
{
public abstract Object getKey(){};
public abstract Object getValue(){};
}
}

方式一:
Map <String,String >  map = new HashMap <String,String >();
map.put( "02", "zhangsan02");
map.put( "03", "zhangsan03");
map.put( "01", "zhangsan01");
map.put( "04", "zhangsan04");

Set <String > keySet  = map.keySet();

Iterator <String > it =keySet.iterator();
while (it.hasNext())
{
    String key  = it.next();
    String value =map.get(key);
    System.out.println( "key=" +key + ":value=" +value);
}
图例:
黑马程序员--集合 - leon_hm - Leon的博客


方式二:
Map <String,String >  map = new HashMap <String,String >();
map.put( "02", "zhangsan02");
map.put( "03", "zhangsan03");
map.put( "01", "zhangsan01");
map.put( "04", "zhangsan04");

Set <Map.Entry <String,String >> entrySet  = map.entrySet();
Iterator <Map.Entry <String,String >> it  = entrySet.iterator();
while (it.hasNext())
{
    Map.Entry <String,String > me  = it.next();
    String key  =me.getKey();
    String value =me.getValue();
    System.out.println( "key=" +key + ":value=" +value);
}
图例:
黑马程序员--集合 - leon_hm - Leon的博客

集合框架的工具类:
Collections
sort(List<T> list) // 根据元素的自然顺序 对指定列表按升序进行排序。
sort(List<T> list, Comparator<? super T> c)  //根据指定比较器产生的顺序对指定列表进行排序。

max(Collection<? extends T> coll) // 根据元素的自然顺序,返回给定 collection 的最大元素。 
max(Collection<? extends T> coll, Comparator<? super T> comp)  //根据指定比较器产生的顺序,返回给定 collection 的最大元素。 

binarySearch(List<? extends Comparable<? super T>> list, T key) //使用二分搜索法搜索指定列表,以获得指定对象。 
binarySearch(List<? extends T> list, T key, Comparator<? super T> c) //使用二分搜索法搜索指定列表,以获得指定对象。 

class CollectionsDemo
{
     public  static  void main(String[] args)
    {
//        sortDemo();
//        maxDemo();
        binarySearchDemo();
    }
    
     public  static  void binarySearchDemo()
    {
        List <String > list  =  new ArrayList <String >();
        list.add( "abcd");
        list.add( "aaa");
        list.add( "z");
        list.add( "kkk");
        list.add( "qq");
        list.add( "abcd");

/*
        Collections.sort(list);


        sop(list);
        //int index =Collections.binarySearch(list,"aaa");
        int index =halfSearch(list,"aaaa");

        sop(index);
*/

         //按照指定的比较器的方式排序
        Collections.sort(list, new StrLenComparator());
        sop(list);
         int index  =halfSearch(list, "aaa", new StrLenComparator());
        sop(index);
    }
    
    //自己实现halfSearch  使用二分搜索法搜索指定列表,以获得指定对象
     public  static  <T >  int halfSearch(List < ?  extends T > list,T key,Comparator < ?  super T > cmp)
    {
         int max,min,mid;
        max =list.size() - 1;
        min = 0;
        
         while(min < =max)
        {
            mid =(max +min) >> 1;
            T t  =list.get(mid);
             int num =cmp.compare(t,key);//使用比较器的顺序
             if(num > 0)
                max =mid - 1;
             else  if(num < 0)
                min =mid + 1;
             else  return mid;
        }

         return  -min - 1;
    }

    //  使用二分搜索法搜索指定列表,以获得指定对象
     public  static  <T >  int halfSearch(List < ?  extends Comparable < ?  super T >> list,T key)
    {
         int max,min,mid;
        max =list.size() - 1;
        min = 0;
        
         while(min < =max)
        {
            mid =(max +min) >> 1;
            Comparable < ?  super T > t  =list.get(mid);
             int num  = t.compareTo(key);//使用对象自身的自然顺序
             if(num > 0)
                max =mid - 1;
             else  if(num < 0)
                min =mid + 1;
             else  return mid;
        }

         return  -min - 1;
    }

     public  static  void maxDemo()
    {
        List <String > list  =  new ArrayList <String >();
        list.add( "abcd");
        list.add( "aaa");
        list.add( "z");
        list.add( "kkk");
        list.add( "qq");
        list.add( "abcd");
        
        Collections.sort(list);
        sop(list);
        String max  =Collections.max(list, new StrLenComparator());

        sop(max);
    }
    

     public  static  void sortDemo()
    {
        List <String > list  =  new ArrayList <String >();
        list.add( "abcd");
        list.add( "aaa");
        list.add( "z");
        list.add( "kkk");
        list.add( "qq");
        list.add( "abcd");

        sop(list);

        Collections.sort(list, new StrLenComparator());

        sop(list);
    }

     public  static  void sop(Object obj)
    {
        System.out.println(obj);
    }
}

class StrLenComparator  implements Comparator <String >
{
     public  int compare(String s1 ,String s2)
    {
         if(s1.length() >s2.length())
             return  1;
         if(s1.length() <s2.length())
             return  - 1;
         //if(s1.length()==s2.length())
             return s1.compareTo(s2);
    }
}

reverseOrder() //返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。 
reverseOrder(Comparator<T> cmp) //返回一个比较器,它强行逆转指定比较器的顺序。 
class StrLenComparator  implements Comparator <String >
{
     public  int compare(String s1,String s2)
    {
         if (s1.length() >s2.length())
        {
             return  1;
        }
         else  if (s1.length() <s2.length())
        {
             return      - 1;
        }
         else
             return  0;
    }
}

class CollectionsDemo2
{
     public  static  void main(String[] args)
    {
        reverseOrderDemo2();
    }

     public  static  void reverseOrderDemo2()
    {
        TreeSet <String > ts  =  new TreeSet <String >(Collections.reverseOrder(  new StrLenComparator())); 
        ts.add( "abcde");
        ts.add( "aaa");
        ts.add( "zz");
        ts.add( "3");
        
        Iterator it  = ts.iterator();
         while (it.hasNext())
        {
            sop(it.next());
        }
    }
    
     public  static  void reverseOrderDemo()
    {
        TreeSet <String > ts  =  new TreeSet <String >(Collections.reverseOrder()); 
        ts.add( "abcde");
        ts.add( "aaa");
        ts.add( "jjj");
        ts.add( "zz");
        
        Iterator it  = ts.iterator();
         while (it.hasNext())
        {
            sop(it.next());
        }
    }

     public  static  void reverseDemo()
    {
        List <String > list  =  new ArrayList <String >();
        list.add( "abcd");
        list.add( "aaa");
        list.add( "z");
        list.add( "kkk");
        list.add( "qq");
         //list.add("abcd");

        sop(list);
        Collections.reverse(list);
        sop(list);
    }


     public  static  void replaceAllDemo()
    {
        List <String > list  =  new ArrayList <String >();
        list.add( "abcd");
        list.add( "aaa");
        list.add( "z");
        list.add( "kkk");
        list.add( "qq");
        list.add( "abcd");

        sop(list);
        Collections.replaceAll(list, "aaa", "qq");
        sop(list);
    }
}

Arrays
Arrays:用于操作数组的工具类
里面都是静态方法

aslist 将数组变成list集合
class ArraysDemo
{
     public  static  void main(String[] args)
    {
         int[] arr  = { 1, 2, 3, 5};

        System.out.println( Arrays.toString(arr));

        String[] arr ={ "abc", "cc", "kkk"};

         /* 把数组变成list集合有什么好处?

            可以使用集合的思想和方法来操作数组中的元素。

            注意:将数组变成集合,不可以使用数组的增删方法。
            因为数组的长度固定。
            contains
            get
            indexOf
            subList
        */

        List <String > list  =Arrays.asList(arr);
        
         //list.add("qq");//java.lang.UnsupportedOperationException

         //System.out.println(list);
         //System.out.println(list.contains("cc"));

         int[] nums  = { 1, 2, 3, 5};
        
         /*
        如果数组中的元素都是对象。那么变成集合时,数组中的元素就直接转成集合中的元素
        如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在
        */

        List < int[] > li =Arrays.asList(nums);
        System.out.println(li);
    }
}

集合变数组
Collection 中toArray
toArray() //返回按适当顺序包含列表中的所有元素的数组(从第一个元素到最后一个元素)。
toArray(T[] a) //返回按适当顺序(从第一个元素到最后一个元素)包含列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。

class CollectionToArray
{
     public  static  void main(String[] args)
    {
        ArrayList <String > al  =  new ArrayList <String >();
        al.add( "abc1");
        al.add( "abc2");
        al.add( "abc3");
    
         /*
        1.指定类型的数组到底要定义多长呢?
          当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。
          当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递的数组。
          所以创建一个刚刚好的数组最优
        
        2.为什么要将集合变数组?
          为了限定对元素的操作。不需要进行增删。

        */


        String[] arr =al.toArray( new String[al.size()]);
        System.out.println(Arrays.toString(arr));
    }
}

高级for循环
格式
for(数据类型 变量名:被遍历的集合(Collection)或者数组)

对集合遍历。
只能获取元素,但是不能对集合进行操作。

迭代器除了遍历,还可以进行remove集合中元素的动作
如果使用ListIterator,还可以在遍历过程中进行增删改查的动作

传统for循环和高级for有什么区别呢?
高级for有一个局限性,必须有被遍历的目标。

建议在遍历数组的时候,还是希望使用传统for,
因为传统for可以定义脚标。

class ForEachDemo
{
     public  static  void main(String[] args)
    {
        ArrayList <String > al  =  new ArrayList <String >();
        
        al.add( "abc1");
        al.add( "abc2");
        al.add( "abc3");
        al.add( "abc4");

        Iterator <String > it =al.iterator();
         while (it.hasNext())
        {
            System.out.println(it.next());
        }

         for(String s :al)
        {
             //s="kk";
            System.out.println(s);
        }
        System.out.println(al);

         int[] arr ={ 3, 5, 1};
         for ( int i :arr)
        {
            System.out.println(i);
        }

        HashMap <Integer,String > hm =  new HashMap <Integer,String >();
        hm.put( 1, "a");
        hm.put( 2, "b");
        hm.put( 3, "c");

         //高级for循环
        Set <Integer > s =hm.keySet();
         for (Integer    i  : s )
        {
            System.out.println(i + ":" +hm.get(i));
        }

         for (Map.Entry <Integer,String > me :hm.entrySet() )
        {
            System.out.println(me.getKey() + ":" +me.getValue());
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值