黑马程序员——Java之集合框架(三)

------------------- Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ---------------------


一、泛型

在Java SE1.5中,增加的一个新的特性:泛型。何谓泛型呢?通俗的说,就是泛泛的指定对象所操作的类型,而不像常规方式一样使用某种固定的类型去指定。泛型的本质就是将所操作的数据类型参数化,也就是说,该数据类型被指定为一个参数。这种参数类型可以使用在类、接口以及方法定义中。用于解决安全问题,是一个安全机制。

1、好处:

在以往的J2SE中,没有泛型的情况下,通常是使用Object类型来进行多种类型数据的操作。这个时候操作最多的就是针对该Object进行数据的强制转换,而这种转换是基于开发者对该数据类型明确的情况下进行的(比如将Object型转换为String型)。倘若类型不一致,编译器在编译过程中不会报错,但在运行时会出错。

所以定义泛型的好处:

(1)将运行时期出现的问题ClasscastEception,转移到了编译时期。方便于程序员解决问题,让运行事情问题减少,增强安全性。

(2)在运行时所有的转换都是强制的,隐式的,避免了强制转换。

(3)提高代码的重用率。

2、泛型类

泛型格式:通过<>未定义要操作的引用数据类型。

 

在使用Java提供的对象时,什么时候使用泛型?

通常在集合框架中很常见。只要见到<>就要定义泛型。

<>里面是用来接收类型的,当使用集合时,将集合要存储的数据类型作为参数传递到<>中即可。

3.泛型方法

泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定。

为了让不同方法操作不同类型,而且类型还不确定。那么可以将泛型定义在方法上。

注意:静态方法不可以访问类上定义的泛型,如果静态方法操作的应用数据类型不明确,可以将泛型定义在方法上(泛型定义在返回值前修饰符后)

 

4.泛型规则限定

1、泛型的参数类型只能是引用类型,而不能是简单类型。

2、可以声明多个泛型参数类型,比如<T, P,Q…>,同时还可以嵌套泛型,例如:<List<String>>

3、泛型的参数类型可以使用extends语句,例如<Textends collection>。

4、泛型的参数类型可以使用super语句,例如< T superchildclass>。

5、泛型还可以使用通配符,例如<? extends ArrayList>

5、扩展

(1)extends语句

使用extends语句将限制泛型参数的适用范围。例如:

<T extends collection> ,则表示该泛型参数的使用范围是所有实现了collection接口的calss。如果传入一个<String>则程序编译出错。

(2)super语句

super语句的作用与extends一样,都是限制泛型参数的适用范围。区别在于,super是限制泛型参数只能是指定该class的上层父类。

例如<T super List>,表示该泛型参数只能是List和List的上层父类。

(3)通配符上限

Vector<? extends 类型1> x = new Vector<类型2>();

类型1指定一个数据类型,那么类型2就只能是类型1或者是类型1的子类

Vector<? extends Number> x = new Vector<Integer>();//这是正确的

Vector<? extends Number> x = new Vector<String>();//这是错误的

 

(4)通配符下限

Vector<? super 类型1>x = new Vector<类型2>();

类型1指定一个数据类型,那么类型2就只能是类型1或者是类型1的父类

Vector<? super Integer> x = new Vector<Number>();//这是正确的

Vector<? super Integer> x = new Vector<Byte>();//这是错误的

 

注意:限定通配符包括自己

 

 

二 、集合框架工具类Collections


1、Collections 和 Collection 的关系?

Collection是集合类的一个顶级接口,其直接继承接口有List与Set,而Collections则是集合类的一个工具类/帮助类,其中提供了一系列静态方法,用于对集合中元素进行排序、搜索以及线程安全等各种操作。

2、常见操作

(1)排序(Sort)

使用sort方法可以根据元素的自然顺序对指定列表按升序进行排序。列表中的所有元素都必须实现 Comparable 接口。此列表内的所有元素都必须是使用指定比较器可相互比较的。

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

根据元素的自然顺序 对指定列表按升序进行排序。

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

根据指定比较器产生的顺序对指定列表进行排序。

(2)取最大值和最小值操作

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

根据元素的自然顺序,返回给定collection 的最大元素。

public static <T> Tmax(Collection<? extends T> coll, Comparator<? super T> comp)

根据指定比较器产生的顺序,返回给定collection 的最大元素。

 

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

根据元素的自然顺序 返回给定 collection 的最小元素。

public static <T> Tmin(Collection<? extends T> coll,Comparator<? super T> comp)

根据指定比较器产生的顺序,返回给定collection 的最小元素。

(3)二分查找

public static <T> intbinarySearch(List<? extends Comparable<? super T>> list, T key)

使用二分搜索法搜索指定列表,以获得指定对象。

public static <T> intbinarySearch(List<? extends T> list, T key, Comparator<? super T>c)

使用二分搜索法搜索指定的比较器对列表进行排序的列表,以获得指定对象。

原理:

public static int binarysearch(List<String> list,String key,Comparator<String> com){
          int max=list.size()-1;
          int min=0;
          while (min<=max){
               int mid=(min+max)>>1;
         String str=list.get(mid);
          //int num=str.compareTo(key);
          int num=com.compare(str, key);
          if (num>0)
              max=mid-1;
          else if (num<0)
              min=mid+1;
          else return mid;
         }
          return -min-1;
    }


(4)替换所有的元素(Fill)

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

<pre name="code" class="java">//练习:使用指定元素替换指定列表中的指定元素。
class Test4{
public static void main(String[] args){  
         List< String> list= new ArrayList< String>();  
         list.add( "a" );  
         list.add( "bbb" );  
         list.add( "www" );  
         System.out.println(list);  
          fillDemo(list,"aaa",1,2); 
		   System.out.println(list);  
    }  
     public static void fillDemo(List<String > list,String str,int start,int end){  
          //第一种方式:  
         List< String> li=list.subList(start, end);  
         Collections. fill(li,str);  
         ListIterator< String> ls=list.listIterator();  
         ListIterator< String> lis=li.listIterator();  
          while (ls.hasNext()){  
              String s=ls.next();  
                    while (lis.hasNext()){  
                             String s1=lis.next();  
                                  s=s1;;  
                   }  
              }  
         }  
          //第二种方式:  
//       for( int x=start;x<=end-1;x++){  
//            list.set(x,str);  
//       }  
    }  


 

(5)替换指定元素(replaceAll)

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

使用另一个值替换列表中出现的所有某一指定值。

(6)反转(Reverse)

public static void reverse(List<?>list)

使用Reverse方法可以根据元素的自然顺序对指定列表按降序进行排序。

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

返回一个比较器,它强行逆转实现了Comparable 接口的对象 collection 的自然顺序。

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

返回一个比较器,它强行逆转指定比较器的顺序。

<pre name="code" class="java"><pre name="code" class="java">public Test4(){
public static void main(String[] args) 
	{
		String s="aaaa";
		Set<String> al=new TreeSet<String>(new MyCompara());
		al.add("bbb");
		al.add("aaaa");
		al.add("dddaa");
		al.add("aabcaa");
		System.out.println(al);
		//Collections.sort(al);
		//Test4.fillDemo(al,"zzz",0,2);
		//Collections.replaceAll(al,"aaa","zzz");
		
		System.out.println(al);
		//int  i=Test4.binarysearch(al,"ddd");
		//String s=al.get(i);
		//System.out.println(s);
	}
}

class MyCompara implements Comparator<String>
{
	public int compare(String s1,String s2){
		int num=new Integer(s1.length()).compareTo(new Integer(s2.length()));
		if(num==0)
			return s1.compareTo(s2);
		return num;
	}
}


 
 


(7)拷贝(Copy)

public static <T> void copy(List<?super T> dest, List<? extends T> src)

用两个参数,一个目标 List 和一个源 List, 将源的元素拷贝到目标,并覆盖它的内容。目标 List 至少与源一样长。如果它更长,则在目标 List 中的剩余元素不受影响。

(8)替换位置(swap)

public static void swap(List<?> list,int i, int j)

在指定列表的指定位置处交换元素。(如果指定位置相同,则调用此方法不会更改列表。)

(9)混排(Shuffling)

混排算法所做的正好与 sort 相反: 它打乱在一个 List 中可能有的任何排列的踪迹。也就是说,基于随机源的输入重排该 List, 这样的排列具有相同的可能性(假设随机源是公正的)。这个算法在实现一个碰运气的游戏中是非常有用的。例如,它可被用来混排代表一副牌的 Card 对象的一个 List 。另外,在生成测试案例时,它也是十分有用的。

public static void shuffle(List<?>list)

使用默认随机源对指定列表进行置换。所有置换发生的可能性都是大致相等的。

public static void shuffle(List<?>list, Random rnd)

使用指定的随机源对指定列表进行置换。所有置换发生的可能性都是相等的,假定随机源是公平的。


三、工具类Arrays


java.util.Arrays类能方便地操作数组,它提供的所有方法都是静态的。

 

基本操作:

(1)数组转换集合(asList)

public static <T> List<T>asList(T... a)

为什么数组转换为集合?

可以使用集合里的特定方法。

注意:将数组变成集合后,不可以使用集合的增删方法,因为数组的长度是固定的,如果增删的话会出现lang.UnsupportedOperationException异常。

asList接受的参数是一个泛型的变长参数,我们知道基本数据类型是无法发型化的,也就是说8个基本类型是无法作为asList的参数的, 要想作为泛型参数就必须使用其所对应的包装类型。


(2)集合转换为数组(toArray())

public Object[] toArray()
public <T> T[] toArray(T[] a)
 
public static void theard_2(){
         List< String> list= new ArrayList< String>();
         list.add( "aaa" );
         list.add( "bad" );
         list.add( "dgfg" );
          String[] s= new String [list.size()];
          String [] arr=list.toArray(s);
         System. err .println(Arrays.toString(arr));
    }


注意:当指定类型的数组长度,小于集合的长度时,那么该方法会创建一个新的数组,长度为集合的长度。

         当指定类型的数组长度,大于集合的长度时,就不会创建新的数组,而是使用传递进来的数组。

为什么将集合转换为数组?

为了限定对元素的操作。

(3)高级for循环

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

for循环和Interator迭代器有什么区别?

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

迭代器除了遍历,还可以进行remove集合元素的操作。

如果使用ListIterator,还可以在遍历的时候对集合中的元素进行增删改查操作。

 

传统的for和高级的for有什么区别?

高级的for有一个局限性,必须由遍历的目标。

(4)可变参数

JDK1.5版本出现的新特性。

方法的可变参数,在使用时可变参数一定要放在最后面。

 

//虽然少定义了多个方法,但是每次都需要new数组进去。

     public static void theard_4( int[] i){
         System. err .println(Arrays.toString(i));
    }
     //可变参数,其实就是上一个数组的简化形式。不用每次手动建立数组对象,
     //只要将要操作的元素作为参数传递进去即可,隐式的将这些元素封装成数组。
     public static void theard_5( int... i){
         System. err .println(Arrays.toString(i));
    }
     public static void main(String[] args) {
          int [] i={1,2,3};
          int [] i1={1,2,3,4,5};
          theard_4(i1);
          theard_5(1,5,6);
    }


(5)静态导入(import static)

例如:import staticjava.util.Arrays.*;导入的是Arrays这个类中所有的静态成员。

注意:当类的方法重名时,需要指定具体的包名。

当方法重名时,指定所属的对象,或类。

 

------------------- Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ---------------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值