黑马程序员_Java基础_集合框架工具类

来源:互联网 发布:mac book air后悔 编辑:程序博客网 时间:2024/04/25 01:46
 一,集合框架工具类Collections

首先要明确CollectionsCollection是两个完全不同的概念,Collection是集合框架中的一员,它是一个根接口,他有很多子接口,其中有我们最常用的ListSet集合。Collections是集合框架的工具类,它有很多方法可以对很多集合进行操作,并且它没有构造函数,它提供的方法都是静态的,因为它能操作的集合都共享它的方法,所以将这些方法定义成静态的。

举个最简单的例子,当我们想要使用一个集合,不许要保证里面的元素唯一,所以我们只可以使用List集合,我们要对List集合排序,但是List集合没有排序功能,所以既可以使用集合框架工具类的CollectionsSort()方法,对List集合进行排序。这就是Collections的强大之处。

 

1sor有两个方法:

public static <T extends Comparable<? super T>> void sort(List<T> list)

<T extends Comparable<? super T>>的含义是:List集合里面存储的元素是未知类型,我们将这个未知类型假设为T类型,也就是泛型,使用该Sort方法,T类型需要实现Comparable接口,Comparable接口也要定义成泛型,它操作的类型是T类型,但是为了提高它的扩展性,所以允许Comparable接口的泛型定义成T或者其父类型。

 

public static <T> void sort(List<T> list,Comparator<? super T> c)

第二各参数传入的是自定义的比较器,对于没有比较性的对象,必须建立自己的比较器。

 

注意:Collections类的Sort方法是不能操作Set集合的,原因是Set集合有TreeSet子类,具有排序的方法。

 

2max()的两个方法:

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

该方法使用来获取集合中排序后的末尾的那个元素,比如:List集合中存入字符串,使用默认的比较器,该方法会返回List集合里面的字符串按自然顺序排序后的最后一个字符串。

Collection<? extends T> coll的含义是:集合的泛型类型是T或者T的子类型。

<T extends Object & Comparable<? super T>>的含义是:T必须是Object类的子类,并且T要实现Comparable接口,Comparable接口的泛型是T或者T的父类型。

 

需求:自定义一个List集合,里面存储不同的字符串,调用sortmax方法,使用默认的比较器输出List集合中字符串结果,然后自定义一个比较器,比较字符串长度,在调用sortmax方法传入自定义比较器,输出结果。


import java.util.*;public class CollectionsDemo1{    public static void main(String[] args) {        ArrayList<String> al = new ArrayList<>();        al.add("sda");        al.add("ss");        al.add("dd");        al.add("klsfj");        System.out.println(al);        //字符串是具有比较性的,所以sort方法采用的是字符串自然排序        Collections.sort(al);        //打印字符串的自然顺序的排序结果        System.out.println(al);        System.out.println(Collections.max(al)); //返回自然派序的最后一个        //使用自定义比较器,对List集合进行排序,该比较器比较的是字符串长度。        Collections.sort(al,new myComp());        System.out.println(al);                System.out.println(Collections.max(al,new myComp()));//返回最大长度    }}//定义比较字符串长度的比较器class myComp 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);    }}


 3binarySearch()的两个方法:

二分查找的前提是集合的元素必须要有序。

public static <T> int binarySearch(List<? extends Comparable<? super T>> list,

                                                                        T key)

该方法是按照默认的比较器,也就是自然顺序对List集合中的元素进行二分查找。比如字符串,会按照字典顺序查找所需要的元素的角标。

 

public static <T> int binarySearch(List<? extends T> list,

                                   T key,

                                   Comparator<? super T> c)

该方法按照自定义的比较器对集合的元素进行查找。

没有比较器的二分查找的原理代码:


public static <T> int myBinarySearch(List<? extends Comparable<? super T>> list,T key) {    int min = 0;    int max = list.size() - 1;    int mid = 0;    while(min<max) {        mid = (min + max)>>1;        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 -num-1;//这是Collections集合的默认原理,当找不到元素所在位置时,将该元素应该所在的位置-1}

有自定义比较器的二分查找原理:

public static <T> int myBinarySearch(List<? extnds Comparable<? super T>> list,T key,Comparator<? super T> c) {    int min = 0 ;    int max = list.size()-1;    int mid = 0;    while(min < max) {        mid = (min + max)>>1;        String str = list.get(mid);        int num = c.compare(str,key);        if(num>0)            max = mid - 1;        else if(num<0)            min = mid + 1;        else            return mid;    }    return -min-1;}

需求:同样是对List集合的String类型的字符串元素进行操作,按照字符串长度,使用binarySearch(),进行二分查找。


import java.util.*;public class CollectionsDemo2{    public static void main(String[] args) {        ArrayList<String> al = new ArrayList<>();        al.add("sda");        al.add("ss");        al.add("dd");        al.add("klsfj");        //首先集合里面的的元素必须是有顺序的        Collections.sort(al,new myComp());        System.out.println(al);        //使用自定义比较器,按照字符串长度查找        int n = Collections.binarySearch(al,"sss",new myComp());        //如果二分查找没有索要查找元素,则返回的是:-(该插入位置)-1        System.out.println(n);    }}//自定义比较器,按照字符串长度比较class myComp 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);    }}

4public static <T> void fill(List<? super T> list,T obj)

使用指定元素替换指定列表中的所有元素。

 

public static <T> boolean replaceAll(List<T> list, T oldVal, T newVal)

List集合中的旧值替换成成指定的新值。

 

public static void reverse(List<?> list)

将集合中的元素顺序反转。


import java.util.*;public class CollectionTest{    public static void main(String[] args) {        List<String> list = new ArrayList<>();        list.add("na");        list.add("bbb");        list.add("sdg");        list.add("dg");        System.out.println(list);        //将List集合中的所有元素替换成yyy        //Collections.fill(list,"yyy");        //System.out.println(list);        //替换List集合中的一部分元素,替换角标为1——2的元素为yyy        tihuan(list,1,3);                //反转替换后的集合元素顺序        Collections.reverse(list);        System.out.println(list);    }//替换过程代码    public static void tihuan(List<String> list,int s,int e) {        for(int i=s;i<e;i++) {            list.remove(i);            list.add(i,"yyy");        }        System.out.println(list);    }}

二,CollectionsreverseOrder()方法:

reverseOrder方法是Collections集合工具类的一个重要方法,所以单独拿出来总结。

 

public static <T> Comparator<T> reverseOrder()

public static <T> Comparator<T> reverseOrder(Comparator<T> cmp)

 

该方法返回一个Comparator比较器,但是该比较器是默认比较器的逆向比较方法。

比如说字符串的默认比较方式是自然顺序,该顺序是通过实现Comparable接口,重写它的compareTo方法,来按照自然顺序比较字符串。当我们将字符串作为元素存储到List集合中时,通过Collections类的sort()方法对字符串排序,那么结果将会是自然顺序排序后的字符串,如果我们将Collections.reverseOrder()作为一个参数传递给sort方法,那么结果将和自然顺序相反。该方法是可以应用到TreeSet集合的,因为TreeSet集合允许接收一个比较器。

请看谢列需求:

需求:将不同长度的字符串作为元素传递给TreeSet集合,按照字符串的长短输出结果,反别输出字符串从长到短和从短到长的两种不同的结果。

 

按照以前的思维我们通常是定义两个比较器,按别通过返回不同的值,来确定字符串的长短,但是学习了CollectionsreverseOrder()方法后,我们可以直接返回一个与原比较器相反的比较器来进行操作。


import java.util.*;public class CollectionsDemo3{    public static void main(String[] args) {    /*  ArrayList<> list = new ArrayList<>();        list.add("shgsj");        list.add("asg");        list.add("dsh");        System.out.println("原List集合:" + list);        Collections.sort(list);        System.out.println("自然排序的结果:" + list);        Collections.sort(list,Collections.reverseOrder());        System.out.println("自然顺序的逆序:" + list);    */                //创建一个TreeSet集合,将自定义比较器的反向比较器传递给Set集合        TreeSet<String> ts = new TreeSet<>(Collections.reverseOrder(new myC()));        //TreeSet<String> ts = new TreeSet<>(Collections.reverseOrder());        ts.add("fssssgdsf");        ts.add("sfsf");        ts.add("sgrrf");        ts.add("sdf");        sop(ts);        iter(ts);  //按照长度然后进行逆序排序;    }        //对集合中的元素进行迭代输出    public static void iter(TreeSet<String> ts) {        Iterator<String> it = ts.iterator();        while (it.hasNext())        {            sop(it.next());        }    }     public static void sop(Object obj) {        System.out.println(obj);    }}//定义一个比较器,按照字符串长度比较class myC 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);    }}

三,之前我们说过Collection中的ArrayList集合几乎替代了VectorArrayListVector集合的用法是一模一样的,虽然Vector集合比ArrayList集合多了线程同步功能,但是因为它的效率低所以即使在多线程中,我们依然还是用ArrayList,然后自己加锁,其实集合框架工具类已经为我们提供了给List集合加锁的方法,我们只需要给该方法传入一个线程不同步的集合,他就能返回给我们一个线程同步的集合。

这些方法是:

public static <T> Collection<T> synchronizedCollection(Collection<T> c)

public static <T> List<T> synchronizedList(List<T> list)

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m)

public static <T> Set<T> synchronizedSet(Set<T> s)

public static <K,V> SortedMap<K,V> synchronizedSortedMap(SortedMap<K,V> m)

public static <T> SortedSet<T> synchronizedSortedSet(SortedSet<T> s)

 

 

四,数组工具类Arrays:

Arrays类和集合框架工具类Collections一样,提供了很多直接操作数组的静态法方发,很多静态方法我们之前已经使用过。

数组和List集合之间是可以相互转换的,转换方法就是Arrays提供的asList()静态方法。

但是将数组转换成集合要注意一下几个问题:

1,数组转换成集合后,不可以对该集合进行增删操作,因为数组的长度是固定不变的,但是可以进行查询操作,包括containsindexOfgetsubList等操作;

2,如果数组是基本类型的数组,那么转换成集合后,集合的元素不是数组中的所有元素,而是这个数组对象。如果我们打印基本数据类型数组转换成集合后的结果,将看到的是一个地址值,也就是说转换后的集合只有一个元素。下面我们将通过一个程序进行验证。


import java.util.*;public class ArraysDemo{    public static void main(String[] args) {        //返回chs数组的字符串表示形式。没学该方法之前我们只能使用StringBuild进行这样的操作。        /*char[] chs = {'a','d','g','r'};        String s = Arrays.toString(chs);//静态方法引用一定不能忘了类        sop(s);//输出:[a,d,g,r]        */        int[] i = {1,3,6,2,1};//如果将基本数据类型数组转换成集合那么,集合中的元素将是这个数组,而不是数组的元素        List<int[]> list = Arrays.asList(i);        sop(list);//打印结果是:[[I@10be6858]        Integer[] li = {1,2,4,6,7};  //引用了数据类型的拆箱和装箱,数组中存储的元素是对象        List<Integer> list2 = Arrays.asList(li);        sop(list2);        //list2.add(new Integer(6));//会抛出UnsupportedOperationException。        sop(list2.contains("6"));    }    public static void sop(Object obj) {        System.out.println(obj);    }}

3,既然数组可以转换成集合,那么集合也一定可以转换成数组,集合转换成数组是使用Collection集合框架中的toArray()方法。

这个方法有两种形式:

Object[] toArray()

<T> T[] toArray(T[] a)

前一个是返回Object类型的数组,后一个是返回泛型类型的数组。

 

(1)为什么要将集合变成数组呢?为了限制对集合中元素的操作,不需要进行增删操作了,可以将集合变成数组,别的用户就不能进行增删操作了。

    当将集合转成数组的时候,如果指定的数组的长度小于等于集合的size,则会生成集合size大小的数组,当指定数组的长度大于集合的size的时候,会生成指定大小的数组,这个大小比集合的size大多少,就对应生成多少个null值放入数组的空位;所以,指定数组的大小最好是集合的size的大小;


import java.util.*;public class CollectionArrays{    public static void main(String[] args) {        ArrayList<String> al = new ArrayList<>();        al.add("dzsfg04");        al.add("dzsfg01");        al.add("dzsfg02");        al.add("dzsfg03");        //String[] st = al.toArray(new String[0]);        String[] st = al.toArray(new String[al.size()]);        System.out.println(Arrays.toString(st));     }    public static void sop(Object obj) {        System.out.println(obj);    }}

五,总结jdk1.5的几个新特性;

我们知道jdk1.5可以说是java发展的一个重大转折点,因为在这个版本增加了很多革命性的功能,所以这是很重要的一个知识点。面试可能会被问到。

1,泛型

2,增强for循环

3,可变参数

4,静态导入

5,自动装箱和拆箱

6,枚举

7,元数据

 

泛型我们已经学习过,增强for循环也已经在java基础知识里面总结过,在这里在比较一下增强for循环和普通for有什么区别:高级for必须要有被遍历的目标;比如打印100hello world,高级for不能完成,传统for却可以。所以建议对数组进行遍历的时候采用传统的for循环,但是集合框架的遍历,高级for也可以使用。

增强的for循环:

语法:

for(数据类型 变量名 :被遍历的集合(Collection)或者数组)

{

}

重点要掌握增强for循环对List集合和对Map集合的操作:


import java.util.*;public class EnhanceFor{    public static void main(String[] args) {        ArrayList<String> al = new ArrayList<>();        al.add("sdfg");        al.add("sdfdf");        al.add("sdaafa");                //使用迭代器迭代List集合        Iterator<String> it = al.iterator();        while (it.hasNext())        {            System.out.println(it.next());        }        //使用增强for循环迭代List集合        for (String s: al )        {            System.out.println(s);        }         //增强for循环对Map集合的迭代        TreeMap<Integer,String> tm = new TreeMap<>();        tm.put(1,"fasd");        tm.put(2,"hasd");        tm.put(3,"kasd");        //方法一:keySet()        Set<Integer> st = tm.keySet();        for (Integer num: st)        {            System.out.println(num + "----" + tm.get(num));        }        //方法二:entrySet()        Set<Map.Entry<Integer,String>> en = tm.entrySet();        for(Map.Entry<Integer,String> me: en)        {            System.out.println(me.getKey() + "======" + me.getValue());        }    }}

可变参数:在Arrays数组工具类中的asList(T... args)方法上,可以就看到它的参数就是一个可变参数的。可变参数其实就是数组的简写形式,不用每一次都手动的建立数组对象,只要将要操作的元素作为参数传递即可。其实底层是JVM将这些参数封装到了一个数组中。
 

使用可变参数的时候要注意,可变参数一定要定义在最后面。


public class Kebiancanshu{    public static void main(String[] args) {        show("sagj",3,5);        show("ds",1,3,5);        show("sda");//可变参数为空,长度为0    public static void show(int i,int j) {        System.out.println(i+j);    }    public static void show(int i,int j,int k) {        System.out.println(i+k+j);    }    public static void show(String s,int... i) {        System.out.println(i.length);    }}

静态导入:导入的是所用静态类或对象中的静态成员。

特别注意:(1)当类名重名时,需要导入具体的包名;(2)当方法名重名是指定具体的类或者对象。

 

静态导入示例:


import static java.util.Arrays.*;//导入了java.util.Arrays的所有静态成员;public class StaticImportDemo{    public static void main(String[] args) {        String[] arr = {"sg","sadg","stga"};        //Arrays.sort(arr);        //可以省略Arrays        sort(arr);        System.out.println(Arrays.toString(arr));//为什么这个Arrays不可以删呢?        //那是因为StaticImportDemo类是Object的子类,Object超类有自己的toString()        //如果不加Arrays,它会认为引用的是超类的toString方法,会抛异常。    }}





0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 9个月宝宝流鼻血怎么办 8个月宝宝流鼻血怎么办 4个月宝宝流鼻血怎么办 20个月宝宝发烧流鼻血怎么办 60天宝宝老鼻塞怎么办 10个月宝宝头被撞到流鼻血怎么办 狗狗受凉吐了怎么办 狗狗咳嗽流鼻涕一直不好怎么办 宝宝感冒咳嗽流鼻涕发烧怎么办 狗狗感冒咳嗽流鼻涕怎么办 9岁儿童咳嗽鼻塞怎么办 三个月大的狗狗流鼻涕怎么办 3个月小狗干呕流鼻涕怎么办 狗狗流鼻涕怎么办有浓 小狗狗感冒了怎么办呢 狗狗一直擤鼻涕怎么办 小狗感冒流黄鼻涕怎么办 六个月宝宝鼻塞流鼻涕怎么办 小狗吃太多吐了怎么办 狗狗晕车一直吐怎么办 狗狗已经晕车了怎么办 狗狗得犬瘟怎么办 泰迪坐车吐了怎么办 小孩感冒流鼻涕带血怎么办 孩子鼻子流鼻涕有血丝怎么办 鼻子过敏流鼻涕有血丝怎么办 孕妇感冒头痛鼻涕带血怎么办 孕妇感冒鼻塞鼻涕带血怎么办 孕晚期感冒流鼻涕打喷嚏怎么办 孕晚期感冒鼻塞流鼻涕怎么办 怀孕初期鼻涕一直流怎么办 孩子一直流鼻水怎么办 9个月宝宝流鼻涕怎么办 8个月婴儿流鼻涕怎么办 3岁宝宝鼻塞咳嗽怎么办 又感冒又咳嗽了怎么办 鼻塞有一个月了怎么办 感冒一直流清水鼻涕怎么办 孩子受凉流清水鼻涕怎么办 一遇冷空气就打喷嚏流鼻涕怎么办 打喷嚏鼻塞流清鼻涕怎么办