黑马程序员-Java基础09

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

集合

1.面相对象语言对事物的体现的都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。 

      2.数组虽然也可以存储对象,但长度是固定的,集合长度是可变的,

3.数组中可以存储基本数据类型,集合只能存储对象

4.集合只用于存储对象,集合长度是可变的,集合存储不同类型的对象。
     
5.集合框架:     因为每一个容器对数据的存储方式都有不同,

                             这个存储方式称之为:数据结构

Collection接口
 

    Collection接口的有两个子接口:
        List和Set,List元素有序,元素可以重复,Set元素无序,元素要求唯一。

    Collection

        |---->List可存放重复元素,元素存取是有序的。因为该集合体系有索引。

            |---->Vector:底层的数据结构是数组,线程安全,但速度慢,已被ArrayList替代。

            |---->ArrayList:底层的数据结构是数组。特点:查询速度很快。但是增删稍慢。线程不同步。

            |---->LinkedList:底层使用的链表数据结构。特点:增删速度很快,查询稍慢。线程不同步。

        |---->Set元素是无序(存入和取出的顺序不一定一致),元素不可以重复

            |---->HashSet:底层数据结构是哈希表,是线程不安全的,不同步。

            |---->TreeSet:可以对Set集合中的元素进行排序

Collection接口的功能:

    1.添加

        boolean add(Object obj):添加单个元素

        boolean addAll(Collection c):添加多个元素

    2.删除

        void clear():移除所有元素

        boolean remove(Object o):移除单个元素,有一个删除,就返回true

        boolean removeAll(Collection c):移除多个元素

    3.判断

        boolean contains(Object obj):判断元素是否存在

        boolean containsAll(Collection c):判断一个集合的元素是否包含在当前集合中

        boolean isEmpty():判断集合是否为空

    4.获取

        Iterator iterator():返回集合上的一个迭代器

        int size():元素个数

    5.获取交集

        boolean retainAll(Collection c):交集

    6.集合变数组

        Object[] toArray()

迭代器Iterator

    迭代器是取出集合中元素的一种方式,会直接访问集合中的元素。

    所以将迭代器通过内部类的形式来进行描述。

    通过容器的iterator()方法获取该内部类的对象。

迭代器的方法:

    boolean hasNext()判断是否还有元素可以迭代

    next()返回迭代的下一个元素,获取的元素默认为Object类

    注意:

    1.迭代器在Collcection接口中是通用的,它替代了Vector类中的Enumeration(枚举)

    2.迭代器的next()方法是自动向下取元素,要避免出现NoSuchElementException

    3 . 迭代器的 next 方法返回值类型是 Object ,所以要记得类型转换

List

    可存放重复元素,元素存取是有序的。因为该集合体系有索引。
 

    List接口功能:

        1.添加元素

            void add(int index, Object element):在指定位置添加指定元素

            boolean addAll(index i,Collection<? extends E> c)

        2.删除元素

            Object remove(int index):返回并删除指定位置的元素

        3.修改元素

            Object set(int index, Object element):修改指定位置的元素

        4.查找元素

            Object get(int index):根据指定索引获取元素

            List<E> subList(int fromIndex, int toIndex)返回列表中指定的fromIndex(包括)和toIndex(不包括)之间的部分视图。

            int indexOf(Object o)返回此列表中第一次出现的指定元素的索引,如不包括,返回-1

            ListIterator listIterator()List特有的迭代器

    List特有迭代器

        ListIterator<E> listIterator():返回按适当顺序在列表的元素上进行迭代的迭代器。

        在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。

        注:ConcurrentModificationException异常是指当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常,这个地方是指在用迭代器的方法操作集合的时候,又用集合本身的方法来操作这个集合,所以抛出这个异常

        在迭代器时,只能用迭代器的方法操作元素,可是Iterator方法是有限的,只能对元素进行判断,取出,删除的操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator

    该接口只能通过List集合的listIterator方法获取。例:ListIterator it = List集合名. listIterator();

    List迭代器特有方法:

        void add(E e) 将指定的元素插入列表(可选操作)。

        boolean hasPrevious()  如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。 

        int nextIndex() 返回对 next 的后续调用所返回元素的索引。         

        E previous() 返回列表中的前一个元素。    

        int previousIndex() 返回对 previous 的后续调用所返回元素的索引。    

        void set(E e) 用指定元素替换 next 或 previous 返回的最后一个元素(可选操作)。

        void remove()从列表中移除由 next 或 previous 返回的最后一个元素(可选操作)。
 

    List实现类

        Vector

        底层的数据结构是数组,查询快,增删慢,线程同步,效率低已被ArrayList替代

    Vector特有方法:

        1.添加元素

            void addElement(Object obj) JDK1.2 后改为了add(Object obj)

        2.获取元素

            Object elementAt(int index) JDK1.2后就改为了get(int index),通过角标拿元素

        3.遍历元素

            Enumeration elements() JDK1.2后就改为Iterator iterator()

            boolean hasMoreElements() JDK1.2后就改为boolean hasNext()

            Object nextElement() JDK1.2后就改为了 Object next()

            Enumeration elements() 

            Enumeration就是枚举,枚举就是Vector特有的取出方式。此接口的功能与 Iterator 接口的功能
    是重复的,Iterator接口添加了一个可选的移除操作,并使用较短的方法名。新的实现应该优先考虑使用I
    terator接口而不是Enumeration接口。
 

Vector取出元素示例代码:

class VectorDemo{  

    public static void main(String[] args){  

        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());  

        }  

    }  

}  


Arraylist

底层的数据结构使用的是数组结构。特点:查询速度很快。但是增删稍慢。线程不同步

    练习:去除ArrayList集合中的重复元素

    思路:新建立一个集合,遍历原集合往新集合里面存,在存之前进行是否有这个元素的判断。

class ArrayListTest   

{  

      public static void sop(Object obj){  

            System.out.println(obj);  

      }  

      public static void main(String[] args){  

            ArrayList al = new ArrayList();  

  

            al.add("java01");  

            al.add("java02");  

            al.add("java01");  

            al.add("java02");  

            al.add("java01");  

            al.add("java03");  

          

            al =  singleElemen(al);  

            sop(al);  

    }  

  

    public static ArrayList singleElement(ArrayList al){  

        //定义一个临时容器。  

        ArrayList newAl = new ArrayList();  

        Iterator it = al.iterator();//使用迭代器  

        while(it.hasNext()){  

            Object obj = it.next();  

            if(!newAl.contains(obj))//判断是否有遍历到元素  

                newAl.add(obj);  

           }  

        return newAl;  

    }  

}  


LinkList

   底层使用的链表数据结构。特点:增删速度很快,查询稍慢,线程不同步。 

LinkList特有方法:

    1.添加元素:

    void addFirst(E e) 将指定元素插入此列表的开头。 

    void addLast(E e) 将指定元素添加到此列表的结尾。 

    2.获取元素:

    E getFirst()返回此列表的第一个元素。 

    E getLast()返回此列表的最后一个元素。 

    3.删除元素:

    E removeFirst()移除并返回此列表的第一个元素。  

    E removeLast()移除并返回此列表的最后一个元素。 

 

{  

    public static void main(String[] args)  

    {  

        LinkedList link = new LinkedList();//创建对象  

        link.add("hello");//添加元素  

        link.add("world");  

        //特有方法:添加在列表开头与末尾  

        link.addFirst("start");  

        link.addLast("over");  

  

        // 获取元素  

        System.out.println("getFirst:" + link.getFirst());  

        System.out.println("getLast:" + link.getLast());  

        // 遍历  

        Iterator it = link.iterator();  

        while (it.hasNext())  

        {  

            String s = (String) it.next();  

            System.out.println(s);  

        }  

    }  

}  

   Set 集合

    Set接口里面存放的是元素是无序唯一的,可以包含null。Set集合是无序的,因此只能用迭代器获取元素。Set的子类包括HashSet和TreeSet

    Set集合的功能和Collection是一致的.

HashSet:

底层数据结构是哈希表。是线程不安全的。不同步。

HashSet是如何保证元素唯一性的呢?

    是通过元素的两个方法,hashCode和equals来完成。

    如果元素的HashCode值相同,才会判断equals是否为true。

    如果元素的hashcode值不同,不会调用equals。

注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法

练习:往hashSet集合中存入自定对象,姓名和年龄相同为同一个人,重复元素。复写hashCode和equals方法


class HashSetTest   

{  

    public static void sop(Object obj){  

        System.out.println(obj);  

    }  

    public static void main(String[] args){  

        HashSet hs = new HashSet();  

  

        hs.add(new Person("a1",11));  

        hs.add(new Person("a2",12));  

        hs.add(new Person("a3",13));  

        hs.add(new Person("a2",12));//添加重复元素,会调用比较器不将此元素添加至列表  

        hs.add(new Person("a4",14));  

  

        Iterator it = hs.iterator();  

  

        while(it.hasNext()){  

            Person p = (Person)it.next();  

            sop(p.getName()+"::"+p.getAge());  

        }  

    }  

}  

  

class Person  

{  

    private String name;  

    private int age;  

    Person(String name,int age){  

        this.name = name;  

        this.age = age;  

    }  

      

    public int hashCode(){//复写hashCode方法 

        System.out.println(this.name+"....hashCode");  

        return name.hashCode()+age*37;  

    }  

  

    public boolean equals(Object obj){//复写equals方法  

         if(!(obj instanceof Person)){ 

            return false;  

         }

         Person p = (Person)obj;  

         System.out.println(this.name+"...equals.."+p.name);  

  

         return this.name.equals(p.name) && this.age == p.age;  

    }  

  

    public String getName(){  

        return name;  

    }  

    public int getAge(){  

        return age;  

    }  

}    


TreeSet

    可以对Set集合中的元素进行排序,底层数据结构是二叉树。

    保证元素唯一性的依据:compareTo方法

    TreeSet排序的第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖compareTo方法。这种方式也成为元素的自然顺序,或者叫做默认顺序。

    TreeSet的第二种排序方式。当元素自身不具备比较性时,或者具备的比较性不是所需要的,这时就需要让集合自身具备比较性。在集合初始化时,就有了比较方式,接受实现Comparator接口的子类对象

    第一种方式:实现Comparable接口

class Person implements Comparable<Person> {  

    private String name;  

    private int age;  

    public Person() {  

    }  

    public Person(String name, int age) {  

        this.name = name;  

        this.age = age;  

    }  

    public String getName() {  

        return name;  

    }  

  

    public void setName(String name) {  

        this.name = name;  

    }  

    public int getAge() {  

        return age;  

    }  

    public void setAge(int age) {  

        this.age = age;  

    }  

    public int compareTo(Person p) {  

        int num = p.age - this.age;  

        //年龄相同的时比较姓名是否相同  

        int num2 = (num == 0) ? this.name.compareTo(p.name) : num;  

        return num2;  

    }  

}    

第二种方式:接受实现Comparator接口的子类对象


TreeSet ts = new TreeSet(MyCompare);  

//定义一个类,实现Comparator接口,覆盖compare方法。  

class MyComart implements Comparator {  

    public int compare(Object o1,Object o2){  //覆盖compare方法

        Student s1 = (Student)o1;  

        Student s2 = (Student)o2;  

        int num = s1.getName().compareTo(s2.getName());  

        if(num==0){  

            return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
            //比较年龄因为Intege已经具有比较性了.直接比就可以  

            /* 

            if(s1.getAge()>s2.getAge()) 

                return 1; 

            if(s1.getAge()==s2.getAge()) 

                return 0; 

            return -1; 

            */  

        }  

        return num;  

    }  

}    


    注:当元素自身不具备比较性,或者具备的比较性不是所需要的,这时需要让容器自身具备比较性,定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。当两种排序都存在时,以比较器为主。    

Map集合
    Map<K,V>:Map存储的是键值对形式的元素,它的每一个元素,都是由键和值两个元素组成,键是不能有重复的,值是可以重复的,每一个键唯一指向一个值
    Map集合与conllection:
        1.Map与Collection在集合框架中属并列存在
        2.Map存储的是键值对
        3.Map存储元素使用put方法,Collection使用add方法
        4.Map集合没有直接取出元素的方法,而是先转成Set集合,在通过迭代获取元素
        5.Map集合中键要保证唯一性
    Map接口的功能:
    1.添加
        V put(K key, V value) :将指定的值与此映射中的指定键关联(可选操作)。
        void putAll(Map<? extends K,? extends V> m):从指定映射中将所有映射关系复制到此映射中(可选操作)。
    2.删除
        void clear():从此映射中移除所有映射关系(可选操作)。
        V remove(Object key) :如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
    3.判断
        boolean containsValue(Object value):如果此映射将一个或多个键映射到指定值,则返回 true。
        boolean containsKey(Object key):如果此映射包含指定键的映射关系,则返回 true。
        boolean isEmpty():如果此映射未包含键-值映射关系,则返回 true。
    4.获取
        V get(Object key):返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
        int size():返回此映射中的键-值映射关系数。
        values():返回此映射中包含的值的 Collection 视图。
        entrySet():
        keySet():
    Map常用类:
    |---->Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低,已被HashMap替代。
    |---->HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,线程不同步,将hashtable替代,jdk1.2.效率高。
    |---->TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序,排序原理与TreeSet相同。
常用操作示例:
class demo   
{  
       public static void main(String[] args) {  
        //建立Map集合  
        Map<String,String> map=new HashMap<String,String>();  
        添加元素,添加元素,如果出现添加时,相同的键。那么后添加的值会覆盖原有键对应值。  
        map.put("01","zhangsan1");  
        map.put("02","zhangsan2");  
        map.put("03","zhangsan3");  
        map.put("04","zhangsan4");  
        sop(map.containsKey("02"));//判断键是否存在  
        sop(map.get("01"));//可以通过get方法的返回值来判断一个键是否存在。通过返回null来判断。  
        sop(map);//打印结果:{04=zhangsan4, 01=zhangsan1, 02=zhangsan2, 03=zhangsan3}  
        Collection<String> coll=map.values();//用values获取map集合中所有的值.  
        sop(coll);//打印结果:[zhangsan4, zhangsan1, zhangsan2, zhangsan3]  
    }  
  
    public static void sop(Object obj) {   //为了打印方便建立一个函数
        System.out.println(obj);  
    }  
}  

Map集合元素的两种取出方式
方式1:Set<k> keySet
    A:先获取键的集合
    B:遍历键的集合,获取每一个键
    C:根据键获取值
    流程:将map中所有的键存入到Set集合。因为set具备迭代器。所以可以用迭代方式取出所有的键,再根据get方法。获取每一个键对应的值。
代码示例
class MapDemo   {  
    public static void main(String[] args) {  
  
        Map<String,String> map=new HashMap<String,String>();  
  
        map.put("01","zhansan01");  
        map.put("02","zhansan02");  
        map.put("03","zhansan03");  
        map.put("04","zhansan04");  
        Set<String> s=map.keySet();//先获取map集合的所有键的Set集合,keySet();  
        System.out.println(map);//有了Set集合。就可以获取其迭代器  
        for(Iterator<String> it=s.iterator(); it.hasNext();) {  
            String key=it.next();  
            String value=map.get(key);//有了键可以通过map集合的get方法获取其对应的值。   
            System.out.println(key+"..."+value);  
        }  
    }  
}  

方式2:Set<Map.Entry<k,v>> entrySet
    A:先获取键值对关系的集合
    B:遍历键值对关系的集合获取每个键值对的关系
    C:通过键值对关系获取键值
    流程:将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry
代码示例:
class MapDemo   {  
    public static void main(String[] args) {  
        Map<Integer,String> map=new HashMap<Integer,String>();  
        map.put(01,"java01");  
        map.put(02,"java02");  
        map.put(03,"java03");  
        map.put(04,"java04");  
   
        Set<Map.Entry<Integer,String>> entrySet=map.entrySet();//将Map集合中的映射关系取出。存入到Set集合中。  
  
        for(Iterator<Map.Entry<Integer,String>> it=entrySet.iterator();it.hasNext();)  {  
            Map.Entry<Integer,String> me=it.next();  
            Integer key=me.getKey();  
            String value=me.getValue();  
            System.out.println(key+"...."+value);  
        }  
    }  
}  
    Entry其实就是Map中的一个static内部接口。
    为什么要定义在内部呢?
    因为只有有了Map集合,有了键值对,才会有键值的映射关系。关系属于Map集合中的一个内部事物。而且该事物在直接访问Map集合中的元素。

HashMap
    底层数据结构是哈希表,可以存入null键null值,线程不安全,效率高.
    练习:使用HashMap存储Student元素,并遍历,要求键是Student类型:表示学生对象(name,age);值是String类型:表示学号.同名同年龄为同一人,为避免加入相同元素,需要复写hashCode和equals方法
/* 
1.描述学生. 
2.定义map容器.将学生作为键.住址作为值,存入. 
3.获取map集合中的元素 
*/  
import java.util.*;  
class Student implements Comparable<Student>
//为了以后方便可能存进去TreeSet集合中去实现Comparable.将学生具备比较性  
{  
    private String name;  
    private int age;  
    Student(String name,int age) {   //将学生name和age初始化
        this.name=name;  
        this.age=age;  
    }  
    public int compareTo(Student s) //覆盖Comparable中的compareTo方法.来比较,先比较age在比较name.    
        int num=new Integer(this.age).compareTo(new Integer(s.age));//Integer是因为age是基本数据类型不具备比较.要转成Integer来实现compareTo方法  
        if(num==0)  
            return this.name.compareTo(s.name);//name是字符串本身就比较比较性.直接使用compareTo方法  
        return num;  
    }  
    //复写hashCode来让存进去的学生保证唯一。为什么要覆盖因为默认比较是比较hash值和内容是否一样,因为存的是hash值所以每次建立对象的时候都不一样  
    //所以要复写hashCode,来比较年龄和姓名是否是相同.这样就能保证学生的唯一性了.  
    public int hashCode() {  
        return name.hashCode()+age*34;  
    }  
    public boolean equals(Object obj) {   //如果年龄相同的话在比较年龄.  
        if(!(obj instanceof Student)){
              //如果穿进去不的不是学生类.抛异常  
              throw new ClassCastException("类型不匹配");  
        } 
        Student s=(Student)obj;  
        return this.name.equals(s.name) && this.age==s.age;  
    }  
  
    public String getName() {  
        return name;  
    }  
    public int getAge()  {  
        return age;  
    }  
    public String toString() {  
        return name+".."+age;  
    }  
}  
  
public class MapTest   {  
    public static void main(String[] args) {  
        HashMap<Student,String> hm=new HashMap<Student,String>();
        //穿件Map集合中的 HashMap集合  
  
        hm.put(new Student("zhangsan01",21),"beijing");
        //往里面添加键值对.将学生作为键.住址作为值  
        hm.put(new Student("zhangsan02",22),"tianjing");  
        hm.put(new Student("zhangsan03",23),"shanghai");  
        hm.put(new Student("zhangsan01",23),"shanghai");  
          
        System.out.println("第一种取出方式:");  
        //第一种去取出方式:Set<k> keySet  
        Set<Student> s=hm.keySet();  
        for(Iterator<Student> it=s.iterator();it.hasNext();)  
        {  
            Student key=it.next();  
            String value=hm.get(key);  
            System.out.println(key+"...."+value);  
        }  
          
        System.out.println("第二种取出方式:");  
        //第二种取出方式:Set<Map.Entry<k,v>> entrySet  
        Set<Map.Entry<Student,String>> entrySet=hm.entrySet();  
        for(Iterator<Map.Entry<Student,String>> it=entrySet.iterator();it.hasNext();) {  
            Map.Entry<Student,String> me=it.next();  
            Student key1=me.getKey();  
            String value1=me.getValue();  
            System.out.println(key1+"..."+value1);  
        }  
    }  
}  

TreeMap
    底层数据结构是二叉树,线程不安全.底层是二叉树,当定义的键值对要求有序时,使用TreeMap。
练习:对学生对象的年龄进行升序排序。
  
class StuNameComparator implements Comparator<Student> {  
         //定义一个比较器类,将其对象作为参数传递给集合  
         public int compare(Student s1,Student s2) {  
            int num = s1.getName().compareTo(s2.getName());
            //字符串本身具有比较性  
            if(num==0){  
                return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
            //Integer是因为age是基本数据类型不具备比较.要转成Integer来实现compareTo方法    
             }    
            return num;  
    }  
}  
     
class  MapTes  {  
    public static void main(String[] args) {  
        TreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameComparator());  
  
        tm.put(new Student("blisi3",23),"nanjing");  
        tm.put(new Student("lisi1",21),"beijing");  
        tm.put(new Student("alisi4",24),"wuhan");  
        tm.put(new Student("lisi1",21),"tianjin");  
        tm.put(new Student("lisi2",22),"shanghai");  
  
         Set<Map.Entry<Student,String>> entrySet = tm.entrySet();  
  
        Iterator<Map.Entry<Student,String>> it = entrySet.iterator();  
  
        while(it.hasNext()) {  
            Map.Entry<Student,String> me = it.next();  
  
            Student stu = me.getKey();  
            String addr = me.getValue();  
            System.out.println(stu+":::"+addr);  
        }  
    }  
}  
 
 获取该字符串中的字母出现的次数,如:"sjokafjoilnvoaxllvkasjdfns";希望打印的结果是:a(3)c(0).....
        通过结果发现,每个字母都有对应的次数,说明字母和次数之间有映射关系。
代码如下:
/*  
思路:1、将字符串转换为字符数组  
      2、定义一个TreeMap集合,用于存储字母和字母出现的次数  
      3、用数组去遍历集合,如果集合中有该字母则次数加1,如果集合中没有则存入  
      4、将TreeMap集合中的元素转换为字符串  
*/        
    
class CharCount     {    
    public static void main(String[] args) {    
        String s="sdfgzxcvasdfxcvdf";    
        System.out.println("s中各字母出现的次数:"+charCount(s));    
    }    
    
    //定义一个方法获取字符串中字母出现的次数    
    public static String charCount(String str) {    
        char[] cha=str.toCharArray();//转换为字符数组    
    
        //定义一个TreeMap集合,因为TreeMap集合会给键自动排序    
        TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();    
    
        int count=0;//定义计数变量    
        for (int x=0;x<cha.length ;x++ ) {    
            if(!(cha[x]>='a'&&cha[x]<='z'||cha[x]>='A'&&cha[x]<='Z'))    
                continue;//如果字符串中非字母,则不计数    
            Integer value=tm.get(cha[x]);//获取集合中的值    
            if(value!=null)//如果集合中没有该字母,则存入    
                count=value;    
            count++;    
            tm.put(cha[x],count);//存入键值对    
            count=0;//复位计数变量    
        }    
             
         StringBuilder sb=new StringBuilder();//定义一个容器    
    
        //遍历集合,取出并以题目格式存入容器中    
        for(Iterator<Character> it=tm.keySet().iterator();it.hasNext();)  {    
            Character ch=it.next();    
            Integer value=tm.get(ch);    
            sb.append(ch+"("+value+")");    
        }    
        return sb.toString();//返回字符串         
    }    
}    
Collections类
    Collections:集合框架的工具类。里面定义的都是静态方法。
 
    Collections和Collection区别
        Collection是集合框架中的一个顶层接口,它里面定义了单列集合的共性方法。它有两个常用的子接口:List,Set;List:对元素都有定义索引。有序的。可以重复元素。Set:不可以重复元素。无序。
 
        Collections是集合框架中的一个工具类。该类中的方法都是静态的,提供的方法中有可以对list集合进行排序,二分查找等方法。
 
    注意:通常常用的集合都是线程不安全的。因为要提高效率。如果多线程操作这些集合时,可以通过该工具类中的同步方法,将线程不安全的集合,转换成安全的。

    Collections的常用方法
    sort:对List集合进行排序
        void sort(List<T> list):
        根据元素的自然顺序 对指定列表按升序进行排序。 列表中的所有元素都必须实现Comparable 接口。此外,列表中的所有元素都必须是可相互比较的。
        void sort(List<T> list,Comparator<? super T> c)
        根据指定比较器产生的顺序对指定列表进行排序。此列表内的所有元素都必须可使用指定比较器相互比较
 
    max:获取最大值
        T max(Collection<? extends T> coll)
        根据元素的自然顺序,返回给定 collection 的最大元素。collection 中的所有元素都必须实现 Comparable接口
        T max(Collection<? extends T> coll,Comparator<? super T> comp)
        根据指定比较器产生的顺序,返回给定 collection 的最大元素。collection 中的所有元素都必须可通过指定比较器相互比较


    binarySearch:对list集合二分查找(必须是有序的)
        int binarySearch(List<? extends Comparable<? super T>> list, T key) 
        使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自然顺序对列表进行升序排序(通过 sort(List) 方法)。
        int binarySearch(List<? extends T> list,T key,Comparator<? super T> c)
        使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据指定的比较器对列表进行升序排序(通过 sort(List, Comparator) 方法)。


    fill:将集合中的元素替换成指定元素
        void fill(List<? super T> list,T obj)使用指定元素替换指定列表中的所有元素。 


    replaceAll:替换
        boolean replaceAll(List<T> list,T oldVal,T newVal)
        使用另一个值替换列表中出现的所有某一指定值。更确切地讲,使用 newVal 替换 list 中满足 (oldVal==null ? e==null : oldVal.equals(e)) 的每个 e 元素。


    reverse:反转
        void reverse(List<?> list)反转指定列表中元素的顺序。


    reverseOrder:强行逆转比较
        Comparator<T>  reverseOrder() 
        返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序。 
        Comparator<T>  reverseOrder(Comparator<T> cmp) 
        返回一个比较器,它强行逆转指定比较器的顺序。 


    List<T> synchronizedList(List<T> list) 返回指定列表支持的同步(线程安全的)列表。
    Map<K,V> synchronizedMap(Map<K,V> m) 返回由指定映射支持的同步(线程安全的)映射。 
    Set<T> synchronizedSet(Set<T> s) 返回指定 set 支持的同步(线程安全的)set 


    swap:指定位置上交换元素
        void swap(List<?> list,int i,int j)
        在指定列表的指定位置处交换元素。(如果指定位置相同,则调用此方法不会更改列表。) 


    shuffle:把集合中的元素随机的排放
        void shuffle(List<?> list)使用默认随机源对指定列表进行置换。所有置换发生的可能性都是大致相等的。
    collections方法示例代码:

public class collection {  
    public static void main(String[] args) {  
        binarySearchDemo();  
     }  
    //sort:对List集合进行排序,swap:指定位置上交换元素  
    public static void sortDemo() {  
        List<String> list = new ArrayList<String>();  
  
        list.add("abcd");  
        list.add("aaa");  
        list.add("zz");  
        list.add("kkkkk");  
        list.add("qq");  
        list.add("z");  
          
        sop(list);//打印结果:[abcd, aaa, zz, kkkkk, qq, z]  
        Collections.sort(list);//根据元素的自然顺序对指定列表按升序进行排序  
        sop(list);//打印结果:[aaa, abcd, kkkkk, qq, z, zz]  
        Collections.sort(list,new StrLenComparator());//根据指定比较器排序  
        sop(list);//打印结果:[z, qq, zz, aaa, abcd, kkkkk]  
        Collections.swap(list,1,2);//指定位置上交换元素,索引为1的元素与索引为2的元素交换  
        sop(list);//打印结果:[z, zz, qq, aaa, abcd, kkkkk]  
      
   }  
      
    //max:获取最大值  
    public static void maxDemo() {  
        List<String> list = new ArrayList<String>();  
  
        list.add("abcd");  
        list.add("aaa");  
        list.add("zz");  
        list.add("kkkkk");  
        list.add("qq");  
        list.add("z");  
        sop(list);  
        String max1 = Collections.max(list/*,new StrLenComparator()*/);  
        sop("max="+max1);//打印结果:max=zz  
        String max2 = Collections.max(list,new StrLenComparator());//传入指定比较器,长度比较  
        sop("max="+max2);//打印结果:max=kkkkk  
    }  
      
    //binarySearch:对list集合二分查找(必须是有序的)  
    public static void binarySearchDemo() {  
        List<String> list = new ArrayList<String>();  
  
        list.add("abcd");  
        list.add("aaa");  
        list.add("zz");  
        list.add("kkkkk");  
        list.add("qq");  
        list.add("z");  
          
        Collections.sort(list);//自然顺序排序  
        int index1 = Collections.binarySearch(list,"aaaa");  
        sop("index1="+index1);  
          
        Collections.sort(list,new StrLenComparator());//自定义比较器排序  
        int index2 = Collections.binarySearch(list,"aaaa",new StrLenComparator());  
        sop("index2="+index2);//打印结果为-5,应该插入位置取负再减去1  
          
        //使用自定义的二分查找方法  
        int index3 = halfSearch(list,"aaaa");  
        sop("index3="+index3);  
        int index4 = halfSearch(list,"aaaa",new StrLenComparator());  
        sop("index4="+index4);//打印结果为-5,应该插入位置取负再减去1  
          
     }  
      
    //自定义二分查找方法  
    public static int halfSearch(List<String> list,String key) {  
        int max,min,mid;  
        max = list.size()-1;  
        min = 0;  
  
        while(min<=max)  
        {  
            mid = (max+min)>>1;//  除以2;  
  
            String str = list.get(mid);  
  
            int num = str.compareTo(key);  
            if(num>0)  
                max = mid -1;  
            else if(num<0)  
                min = mid + 1;  
            else  
                return mid;  
        }  
        return -(min+1);  
    }  
  
    public static int halfSearch(List<String> list,String key,Comparator<String> cmp) {  
        int max,min,mid;  
        max = list.size()-1;  
        min = 0;  
  
        while(min<=max) {  
            mid = (max+min)>>1;//  /2;  
  
            String str = list.get(mid);  
  
            int num = cmp.compare(str,key);  
            if(num>0)  
                max = mid -1;  
            else if(num<0)  
                min = mid + 1;  
            else  
                return mid;  
        }  
        return -min-1;  
    }  
      
    //fill:将集合中的元素替换成指定元素  
    public static void fillDemo() {  
        List<String> list = new ArrayList<String>();  
  
        list.add("abcd");  
        list.add("aaa");  
        list.add("zz");  
        list.add("kkkkk");  
          
        sop(list);  
        Collections.fill(list,"pp");  
        sop(list);  
        /*测试结果: 
        [abcd, aaa, zz, kkkkk] 
        [pp, pp, pp, pp]*/  
    }  
      
    //replaceAll:替换,reverse:反转  
    public static void replaceAllDemo() {  
  
  
        List<String> list = new ArrayList<String>();  
  
        list.add("abcd");  
        list.add("aaa");  
        list.add("zz");  
        list.add("kkkkk");  
  
        sop(list);  
        //打印结果:[abcd, aaa, zz, kkkkk]  
        Collections.replaceAll(list,"aaa","pp");  
        sop(list);  
        //打印结果:[abcd, pp, zz, kkkkk]  
        Collections.reverse(list);  
        sop(list);  
        //打印结果:[kkkkk, zz, pp, abcd]  
  
    }  
      
    //reverseOrder:强行逆转比较  
    public static void orderDemo() {  
        //将指定比较器逆转比较  
        TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new StrLenComparator()));  
  
        ts.add("abcde");  
        ts.add("aaa");  
        ts.add("k");  
        ts.add("cc");  
  
        Iterator it = ts.iterator();  
        while(it.hasNext())  
        {  
            System.out.println(it.next());  
        }  
        //打印结果:由长到短  
    }  
      
    //shuffle:把集合中的元素随机的排放  
    public static void shuffleDemo() {  
        List<String> list = new ArrayList<String>();  
  
        list.add("abcd");  
        list.add("aaa");  
        list.add("zz");  
        list.add("kkkkk");  
        list.add("qq");  
        list.add("z");  
  
        sop(list);//打印结果:[abcd, aaa, zz, kkkkk, qq, z]  
        Collections.shuffle(list);  
        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;  
        return s1.compareTo(s2);  
    }  
}  

Arrays类
    此类包含用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂。 
 
    (一)将数组转换为List集合
        List<T> asList(T... a)  返回一个受指定数组支持的固定大小的列表 ,即将数组转换为集合.
    把数组变成list集合有什么好处?
        可以使用集合的思想和方法来操作数组中的元素.
    注意:
        1.将数组变成集合,不可以使用集合的增删方法,因为数组的长度是固定.如果增删,会发生UnsupportedOperationException异常(不可操作异常).
        2.如果数组中的元素都是对象,那么变成集合时,数组中的元素就直接转成集合中的元素.如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的一个元素存在.
public class  ArraysDemo {  
    public static void main(String[] args) {  
        int[] arr = {2,4,5};  
        System.out.println(Arrays.toString(arr));  
  
        String[] strarr = {"abc","cc","kkkk"};  
  
        List<String> list = Arrays.asList(strarr);  
        //sop("contains:"+list.contains("cc"));  
          
        //如果使用集合中的增删方法,会抛出异常  
        //list.add("qq");//UnsupportedOperationException,  
  
        //sop(list);  
  
        int[] intnums = {2,4,5};  
        List li1 = Arrays.asList(intnums);  
        System.out.println(li1);
        //数组中的元素都是基本数据类型,那么会将该数组作为集合中的一个元素存在,[[I@1fb8ee3]  
          
        Integer[] nums = {2,4,5};  
        List<Integer> li2 = Arrays.asList(nums);  
        System.out.println(li2);//打印结果:[2, 4, 5]  
          
    }  
}  

    (二)集合变数组。
     Collection接口中的toArray方法。
    1.指定类型的数组到底要定义多长呢?
        当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。
        当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组。所以创建一个刚刚好的数组最优。
    2.为什么要将集合变数组?
        为了限定对元素的操作。不需要进行增删了。
[java] view plaincopy
class  CollectionToArray  
{  
    public static void main(String[] args)   
    {  
        ArrayList<String> al = new ArrayList<String>();  
  
        al.add("abc1");  
        al.add("abc2");  
        al.add("abc3");  
        String[] arr = al.toArray(new String[al.size()]);  
        System.out.println(Arrays.toString(arr));  
        //打印结果:[abc1, abc2, abc3]  
    }  
}  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值