黑马程序员----集合框架工具类,几个新特性
2015-07-14 22:30
579 查看
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
max方法:取出List集合中的最大值同样有两种方式:1.按照自然顺序,2.传入比较器。
binarySearch方法:使用二分法对List进行元素查找,需要List有序。
fill方法:使用参数替换List中所有元素。
replaceAll方法:使用新值替换所有旧值。
reverse方法:反转List中所有元素。
reverseOrder方法:返回一个逆转了的比较器或者元素的自然顺序。
synchronizedList,synchronizedMap,synchronizedSet,传入不同步的集合返回同步的集合。
内部实现:例如synchronizedList返回一个SynchronizedList对象,该对象实现List接口,该对象所在类内部实现所有List的方法
方法的实现方式是:1.使用同步代码块包起来。2.调用传入的List对象的对应方法
例如SynchronizedList的add方法如下
add(E)
{
synchronized(mutex)
{
list.add();
}
}
asList方法:
*将数组转为list集合。
好处:使用集合的思想操作数组。
注意:将数组变成集合,不可以使用集合的增删方法,因为数组长度不可变。
特点:如果数组中的元素是引用数据类型,那么就是将数组中的元素作为集合中的元素,如果数组中的元素是基本数据类型,
那么就会将数组本身作为集合中的元素。
*扩展:将集合转为数组。
Collection接口的toArray方法。
toArray方法需要传入一个指定类型的数组参数,其中需要指定数组长度:
1.指定的长度小于集合中元素,那么就会开辟新的空间。
2.指定长度大于集合中元素个数,那么就会自动添加null到数组中后几个。
因此指定长度最好就等于集合中元素个数。
好处:限定对集合元素的操作。例如我们对外传递只传递数组格式,那么外界就不能添加删除了。
底层遍历使用的依然是迭代器。
使用这种方法只能获取元素,不能操作集合。
局限性:必须要有一个遍历的集合或数组。
建议:遍历数组时使用传统for,因为传统for有下标,而对于数组来说,下标是很重要的特性。
用处:如果只是取出集合数组中的元素,那么考虑使用增强for,毕竟其语法简单。
定义:show(int... arr)等价于show(int[] arr)
调用:show(1,2,3)等价于 show(new int[]{1,2,3})就是说这一步由jvm来完成。
注意:可变参数只能定义在参数列表的最后。
show(int... arr,int i)//错误
show(int... arr,String i)//错误
show(int i,int... arr)//可以
例如 import java.util.*;java的util包中的所有类。
静态导入:import static.....导入的是某个类中的静态成员;
例如 import static java.util.Arrays.*;导入的是Arrays类下的所有静态成员。
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1.Collections
这是一个用来操作集合的工具类,既然是个工具类,也就是说它没有特有属性,也就是说该类不会创建对象,而是使用其内部的静态方法来对集合进行排序,求最值,查找等复杂操作,调用该类方法可以为我们省去大量的自己写方法的时间。常用方法:
sort方法:对集合List进行排序,两个方式:1.按照集合元素自己的自然顺序,2.传入比较器。max方法:取出List集合中的最大值同样有两种方式:1.按照自然顺序,2.传入比较器。
binarySearch方法:使用二分法对List进行元素查找,需要List有序。
fill方法:使用参数替换List中所有元素。
replaceAll方法:使用新值替换所有旧值。
reverse方法:反转List中所有元素。
reverseOrder方法:返回一个逆转了的比较器或者元素的自然顺序。
synchronizedList,synchronizedMap,synchronizedSet,传入不同步的集合返回同步的集合。
内部实现:例如synchronizedList返回一个SynchronizedList对象,该对象实现List接口,该对象所在类内部实现所有List的方法
方法的实现方式是:1.使用同步代码块包起来。2.调用传入的List对象的对应方法
例如SynchronizedList的add方法如下
add(E)
{
synchronized(mutex)
{
list.add();
}
}
shuffle方法:对集合中元素进行随机排放。
2.Arrays
对数组操作的封装类,内部包含的都是跟数组有关的操作,使用该类可以大大减少我们的工作量。常用方法:
toString方法:asList方法:
*将数组转为list集合。
好处:使用集合的思想操作数组。
注意:将数组变成集合,不可以使用集合的增删方法,因为数组长度不可变。
特点:如果数组中的元素是引用数据类型,那么就是将数组中的元素作为集合中的元素,如果数组中的元素是基本数据类型,
那么就会将数组本身作为集合中的元素。
*扩展:将集合转为数组。
Collection接口的toArray方法。
toArray方法需要传入一个指定类型的数组参数,其中需要指定数组长度:
1.指定的长度小于集合中元素,那么就会开辟新的空间。
2.指定长度大于集合中元素个数,那么就会自动添加null到数组中后几个。
因此指定长度最好就等于集合中元素个数。
好处:限定对集合元素的操作。例如我们对外传递只传递数组格式,那么外界就不能添加删除了。
3.Collections,Arrays常用方法测试:
/* 集合框架工具类: 1.Collections: 测试其方法的使用;sort,max,binarySearch,fill(全部替换,实现部分替换),replaceAll,reverse,reverseOrder,shuffle,synchronizedList,synchronizedMap, synchronizedSet。 2.Arrays: 数组转集合,用处,方法,注意事项 Arrays.adList方法,返回一个指定类型的list集合 注意:不能改变集合的长度,因此一般不能添加和删除 集合转数组,用处,方法,注意事项 */ package com.helong.test; import java.util.*; class MyComp implements Comparator<String> { public int compare(String s1,String s2) { if(s1.length()==s2.length()) return s2.compareTo(s1); else return s2.length()-s1.length(); } } class Test { public static void main(String[] args) { List<String> list=new ArrayList<String>(); list.add("adb"); list.add("b"); list.add("accb"); list.add("baaba"); sop("原始字符串:"+list); //使用集合元素的自然顺序排序 Collections.sort(list); sop("自然顺序排序:"+list); //打乱集合中的元素 Collections.shuffle(list); sop("打乱集合:"+list); //按照字符串长度排序 Collections.sort(list,new MyComp()); sop("按照字符串长度逆序:"+list); Collections.shuffle(list); //二分查找,必须保证有序 Collections.sort(list); sop("自然排序后字符串:"+list); sop("元素所在位置:"+Collections.binarySearch(list,"accd")); //对于二分查找有一个知识点:如果找不到,那么返回的是key的插入点位置的负值再减1,例如此处accd的插入点为1,负值就是-1再减1就是-2 sop("元素所在位置:"+Collections.binarySearch(list,"accb")); Collections.replaceAll(list,"b","ee"); sop("b被eee替换后:"+list); Collections.reverse(list); sop("反转后:"+list); //reverseOrder按照自然元素逆向排序 Collections.sort(list,Collections.reverseOrder()); sop("逆向排序:"+list); //按照比较器的逆序排序 Collections.sort(list,Collections.reverseOrder(new MyComp())); sop("按照长度逆向排序:"+list); //使用fill实现部分替换 myFill(list,1,2,"hahah"); //数组转成集合 String[] strs={"adf","vvsd","qwer","xxxx","sdf"}; List<String> temp=Arrays.asList(strs); sop(temp); //不能进行添加删除等会改变数组长度的操作 //并不是不能使用这些方法,而是当在这些方法内因为添加或者删除而造成长度改变时,会报异常 //证明:当我们删除一个不存在的元素时,是没有报错的,这说明本质不是add或者remove而是长度被改变 //temp.add("adfaf"); //temp.remove("adf"); } private static void myFill(List<String> list,int start,int end,String str) { List<String> head=list.subList(0,start); List<String> temp=list.subList(start,end); List<String> rear=list.subList(end,list.size()); Collections.fill(temp,str); head.addAll(temp); head.addAll(rear); sop(head); } private static void sop(Object obj) { System.out.println(obj); } }运行图:
4.手写实现部分Collections方法
/* sort,max,binarySearch,fill(全部替换,实现部分替换), replaceAll,reverse,reverseOrder,shuffle 手写工具类实现上述方法处理ArrayList集合 泛型的使用并不熟练 什么时候该用,怎么正确使用限定达到程序要的效果 不懂哪里没有确定集合元素类型导致了编译期间的注意 */ package com.helong.test2; import java.util.*; class MyCollections { //构造函数私有化,严谨 private MyCollections(){} private static <T extends Comparable<? super T>> void arrayToList(ArrayList<T> al,T[] temp) { for(int i=0;i<temp.length;i++) al.add(temp[i]); } //调用方法时能够使用Comparable类及其子类 //主要作用是将T和Comparable之间产生关系,使用多态特性 //<T extends Comparable<? super T>>这句具体的限定关系还不明确 private static <T extends Comparable<? super T>> void listToArray(Comparable[] temp,ArrayList<T> al) { for(int i=0;i<temp.length;i++) { temp[i]=al.get(i); } } //============================================================================== public static <T extends Comparable<? super T>> void sort(ArrayList<T> al) { if(al.size()==0)return ; if(!(al.get(0) instanceof Comparable))throw new ClassCastException("元素不具有可比性,无法进行排序操作!"); //默认从小到大排序 Comparable[] temp=new Comparable[al.size()]; listToArray(temp,al); for(int i=0;i<temp.length-1;i++) { int k=i; for(int j=i+1;j<temp.length;j++) { if(temp[j].compareTo(temp[k])<0) k=j; } if(k!=i) { Comparable t=temp[k]; temp[k]=temp[i]; temp[i]=t; } } al.clear(); arrayToList(al,(T[])temp); } //重载sort方法,提供比较器进行自定义排序顺序 public static <T extends Comparable<? super T>> void sort(ArrayList<T> al,Comparator<T> comp) { if(al.size()==0)return ; if(!(al.get(0) instanceof Comparable))throw new ClassCastException("元素不具有可比性,无法进行排序操作!"); //默认从小到大排序 Comparable[] temp=new Comparable[al.size()]; listToArray(temp,al); for(int i=0;i<temp.length-1;i++) { int k=i; for(int j=i+1;j<temp.length;j++) { //此处修改为使用比较器方法比较大小 //将排序方式改为了从大到小 if(comp.compare((T)temp[j],(T)temp[k])<0) k=j; } if(k!=i) { Comparable t=temp[k]; temp[k]=temp[i]; temp[i]=t; } } al.clear(); arrayToList(al,(T[])temp); } //============================================================================== public static <T extends Comparable<? super T>> T max(ArrayList<T> al) { T max=al.get(0); for(int i=1;i<al.size();i++) { if(al.get(i).compareTo(max)>0) max=al.get(i); } return max; } //============================================================================== //使用二分查找元素位置,如果不存在,返回 : -(插入点)-1 public static <T extends Comparable<? super T>> int binarySearch(ArrayList<T> al,T key) { sort(al); int insertPoint=0; for(int min=0,max=al.size()-1,mid=(min+max)/2;min<=max;mid=(min+max)/2) { int temp=al.get(mid).compareTo(key); if(temp==0) return mid; else if(temp>0) max=mid-1; else min=mid+1; insertPoint=min; } return -insertPoint-1; } //============================================================================== public static <T> void fill(ArrayList<T> al,T newElement) { int length=al.size(); al.clear(); for(int i=0;i<length;i++) al.add(newElement); } //============================================================================== public static <T extends Comparable<? super T>> boolean replaceAll(ArrayList<T> al,T oldElements,T newElement) { boolean flag=false; for(int i=0;i<al.size();i++) { if(al.get(i).equals(oldElements)) { al.set(i,newElement); flag=true; } } return true; } //============================================================================== public static <T> void reverse(ArrayList<T> al) { if(al.size()<=1)return ; for(int i=0;i<al.size()/2;i++) { T temp=al.get(i); al.set(i,al.get(al.size()-1-i)); al.set(al.size()-1-i,temp); } } //============================================================================== //思路:al中的元素随机取出放到数组中,最后将数组的值赋回给al public static <T extends Comparable<? super T>> void shuffle(ArrayList<T> al) { Comparable[] temp=new Comparable[al.size()]; Random random=new Random(); for(int i=0;i<temp.length;i++) { int index=random.nextInt(al.size()); temp[i]=al.get(index); al.remove(index); } arrayToList(al,(T[])temp); } //============================================================================== //该方法作用是:返回一个比较器,强行逆转了元素按自然顺序排序,比较器提供的排序顺序时与自然顺序相反的 public static <T extends Comparable<? super T>> Comparator<T> reverseOrder() { return new Comparator<T>(){//注意此处不要忘了T public int compare(T t1,T t2) { return t2.compareTo(t1); } }; } //============================================================================== //该方法作用:通过传入一个比较器,返回与比较器相反的比较器 //例如将reverseOrder返回值(从大到小排序)传入该方法,那么就会得到一个从小到大排序的比较器 public static <T extends Comparable<? super T>> Comparator<T> reverseOrder(Comparator comp)//此处Comparator不能设置泛型类型,不懂为啥? { return new Comparator<T>(){ public int compare(T t1,T t2) { return comp.compare(t2,t1); } }; } } class Test2 { public static void main(String[] args) { ArrayList<Integer> array=new ArrayList<Integer>(); array.add(12);array.add(8);array.add(5);array.add(8);array.add(11); sop(array); //测试sort方法 MyCollections.sort(array); sop("排序后的集合:"+array); //测试max方法 sop("当前集合中最大值:"+MyCollections.max(array)); //测试binarySearch方法 sop("5在集合中的位置:"+MyCollections.binarySearch(array,5)); sop("4在集合中的位置:"+MyCollections.binarySearch(array,4)); sop("9在集合中的位置:"+MyCollections.binarySearch(array,9)); //测试replaceAll方法 MyCollections.replaceAll(array,8,24); sop("使用24替换8:"+array); //测试reverse方法 MyCollections.reverse(array); sop("集合反转:"+array); //测试shuffle方法 MyCollections.shuffle(array); sop("随机打乱集合:"+array); MyCollections.shuffle(array); sop("再次随机打乱集合:"+array); //测试reverseOrder(),sort(array,comp) MyCollections.sort(array,MyCollections.reverseOrder()); sop("使用reverseOrder返回的比较器对集合进行排序:"+array); //测试reverseOrder(comp),将reverseOrder()的返回值作为参数传给reverseOrder(comp)并返回相反的比较器, //此处,也就是从小到大排序方式 MyCollections.shuffle(array); sop("随机打乱集合:"+array); MyCollections.sort(array,MyCollections.reverseOrder(MyCollections.reverseOrder())); sop("将reverseOrder()返回的比较器作为参数传给reverseOrder(comp)得到一个\n相反的比较器作为参数传给sort进行排序:"+array); //测试fill方法 MyCollections.fill(array,88); sop("用88填充集合:"+array); } private static void sop(Object obj) { System.out.println(obj); } }
5.集合框架小结
虽然在使用工具类的时候,没有什么问题,但是当自己去实现这些方法时,遇到了很多问题,其中最明显的就是对泛型的使用存在很多问题,尤其是泛型的高级应用,也就是泛型限定的使用非常不好,很多地方不明白为什么使用向上限定或者向下限定,不过还是写出来了,要在以后的学习中重点掌握这一部分,因为泛型是非常重要且实用的一个特性。它使得写出来的程序即有多态般的灵活性,又有自己的安全性。6.JDK1.5后几个新特性
增强for循环(简化代码书写):
foreach:被循环对象需要实现Iterable接口。
格式:for(集合数据类型 变量名 : 被遍历的集合或者数组){.....}底层遍历使用的依然是迭代器。
使用这种方法只能获取元素,不能操作集合。
局限性:必须要有一个遍历的集合或数组。
建议:遍历数组时使用传统for,因为传统for有下标,而对于数组来说,下标是很重要的特性。
用处:如果只是取出集合数组中的元素,那么考虑使用增强for,毕竟其语法简单。
/* 增强for循环 for(集合中数据类型 var : 集合或者数组) {........} Java升级:简化书写 对于遍历集合来说,它底层使用的依然是迭代器。 与传统for循环比较: 增强for必须要有一个可以遍历的集合或者数组 建议:在遍历数组时,使用传统for,因为传统for有下标 局限:增强for只能获取元素,不能操作集合。 迭代器:不仅可以获取元素,还能remove 列表迭代器:甚至可以增删改查 */ package com.helong.foreachdemo; import java.util.*; class ForeachDemo { public static void main(String[] args) { ArrayList<String> al =new ArrayList<String>(); al.add("hl1"); al.add("hl2"); al.add("hl3"); sop("迭代器:"); for(Iterator<String> it = al.iterator();it.hasNext();) { sop(it.next()); } sop("传统for:"); for(int i=0;i<al.size();i++) { sop(al.get(i)); } sop("增强for:"); for(String str : al) { sop(str); } HashMap<Integer,String> hm=new HashMap<Integer,String>(); hm.put(1,"ldy1"); hm.put(2,"ldy2"); hm.put(3,"ldy3"); sop("keySet迭代器:"); for(Iterator<Integer> it=hm.keySet().iterator();it.hasNext();) { Integer temp=it.next(); sop(temp+":::"+hm.get(temp)); } sop("增强for:"); for(Integer i : hm.keySet()) { sop(i+"::::"+hm.get(i)); } sop("entrySet迭代器:"); for(Iterator<Map.Entry<Integer,String>> it=hm.entrySet().iterator();it.hasNext();) { Map.Entry me=it.next(); sop(me.getKey()+"--"+me.getValue()); } sop("增强for:"); for(Map.Entry<Integer,String> me : hm.entrySet()) { sop(me.getKey()+"---"+me.getValue()); } } private static void sop(Object obj) { System.out.println(obj); } }运行图:
可变参数(简化代码书写):
取代数组参数的用法,不用每次都建立数组,而是由jvm来自动完成。定义:show(int... arr)等价于show(int[] arr)
调用:show(1,2,3)等价于 show(new int[]{1,2,3})就是说这一步由jvm来完成。
注意:可变参数只能定义在参数列表的最后。
show(int... arr,int i)//错误
show(int... arr,String i)//错误
show(int i,int... arr)//可以
/* 可变参数,JDK1.5新特性 注意:可变参数必须放到参数列表的最后位 */ package com.helong.paramdemo; class ParamDemo { public static void main(String[] args) { function(1,2,3); function(1,2,3,4,5,6,7); //function(1,2,3,"str"); function("str",1,2,3); } private static void function(int... arr) { System.out.println(arr.length); } private static void function(String str,int... arr) { System.out.println(arr.length); } }运行图:
静态导入(简化代码书写):
普通导入:import.....导入的是某个包中的类;例如 import java.util.*;java的util包中的所有类。
静态导入:import static.....导入的是某个类中的静态成员;
例如 import static java.util.Arrays.*;导入的是Arrays类下的所有静态成员。
//静态导入:导入的是某个类的静态成员 //普通导入:导入的是某个包中的类 package com.helong.staticimportdemo; import java.util.*; import static java.util.Arrays.*; //导入了Arrays类中的静态成员 class StaticImportDemo { public static void main(String[] args) { int[] arr={1,2,3}; sort(arr); System.out.println(Arrays.toString(arr)); } }运行图:
新特性小结:
我们可以看到,这三个新特性的目的都是为了简化代码书写。------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
相关文章推荐
- [异能程序员]第五章 出手(第一更)
- 黑马程序员----学习集合遇到的两个问题
- 黑马程序员——Java基础--IO(四)
- 黑马程序员——基础学习(十一)集合框架
- Java面试题(亲身经历)
- 我是一个随波逐流的程序员
- 腾讯地图实习面试
- 工作体会--程序员做了4年+的稍许感受
- 读<<卓有成效的程序员>>之感
- 不少程序员都会碰到的三个面试题
- 黑马程序员——基础学习(十)API中Arrays、Integer、正则表达式以及日期类的相关应用
- 大话设计模式(十三 有了门面,程序员的程序会更加体面!)
- 黑马程序员——我的学习感悟....
- 链表面试题小结
- 关于PHP程序员解决问题的能力
- 面试题43:n个骰子的点数
- 面试题12打印1到最大的n位数
- 程序员最艰难的十大任务
- leetcode题目难度及面试频率
- 支付宝面试