您的位置:首页 > 职场人生

黑马程序员----集合框架工具类,几个新特性

2015-07-14 22:30 579 查看
------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培训、期待与您交流! -------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: