黑马程序员——集合——泛型、Collections和Arrays
来源:互联网 发布:天刀捏脸数据库男性萌 编辑:程序博客网 时间:2024/05/16 03:49
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、泛型
了解泛型之前我们先看一下没有泛型会产生什么结果:
package com.leaf.test;import java.util.ArrayList;import java.util.List;class ListDemo{public static void main(String[] args) {List list = new ArrayList();list.add("abc");list.add("abc");list.add(new Integer(1));String str = (String)list.get(2);}}result:
定义了一个List类型的集合,先向其中加入了两个字符串类型的值,随后加入一个Integer类型的值。这是完全允许的,因为此时list默认的类型为Object类型。在之后的循环中,由于忘记了之前在list中也加入了Integer类型的值或其他编码原因,很容易出现类似于result中的错误。因为编译阶段正常,而运行时会出现“java.lang.ClassCastException”异常。因此,导致此类错误编码过程中不易发现。
在我们平时的代码中,我们发现主要存在两个问题:
1.当我们将一个对象放入集合中,集合不会记住此对象的类型,当再次从集合中取出此对象时,改对象的编译类型变成了Object类型,但其运行时类型任然为其本身类型。
2.因此,//1处取出集合元素时需要人为的强制类型转化到具体的目标类型,且很容易出现“java.lang.ClassCastException”异常。
那么有没有什么办法可以使集合能够记住集合内元素各类型,且能够达到只要编译时不出现问题,运行时就不会出现“java.lang.ClassCastException”异常呢?答案就是使用泛型。
泛型的基本使用:
示例(错误):
示例(正确):
import java.util.*;/*泛型的最基本使用*/package com.leaf.generic;import java.util.ArrayList;import java.util.List;class GenericDemo{public static void main(String[] args) {List<String> list = new ArrayList<String>();list.add("abc");System.out.println(list);}}result:
泛型的定义:
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型是提供给javac编译器使用的,可以限定集合输入的类型,让编译器挡住源程序的非法输入, 是程序的运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值和原始类型完全 一样,由编译器生成的字节码文件会去掉泛型的类型信息,只要能跳过编译器,就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合,再调用其add方法即可
泛型的原理及深层使用:泛型的术语、泛型的通配符、限定通配符
泛型的术语:
ArrayList<E>中的E称为类型变量或者类型参数
整个ArrayList<Integer>称为参数化的类型
ArrayList<Integer>中的Integer称为类型参数的实例或者实际类型参数
ArrayList<Integer>中的<>称为typeOf
ArrayList称为原始类型
参数化类型与原始类型的兼容性
参数化类型可以引用一个原始类型的对象,编译报告警告,例如:
Collection<String> c = new Vector();//可不可以就是编译器的一句话
原始类型可以引用一个参数化类型的对象,编译器警告,例如:
Collection c = new Vector<String>();
参数化类型不考虑参数的继承关系
Vector<String> v = newVector<Object>();//错误
Vector<Object> v = newVector<String>();//错误
在创建数组实例时,数组的元素不能使用参数化的类型,例如:
Vector<Integer> vectorList[] = newVector<Integer>[10];
下列代码可以:
Collection c = newCollection<String>();
Collection<Object> col = c;
是不是看不懂上面这些东西,下面来写一个示例:
package com.leaf.generic;import java.lang.reflect.Constructor;import java.lang.reflect.InvocationTargetException;import java.util.ArrayList;import java.util.Collection;public class GenericTest {public static void main(String[] args) throws NoSuchMethodException,SecurityException, InstantiationException, IllegalAccessException,IllegalArgumentException, InvocationTargetException {// 没有泛型的集合,会报警告ArrayList col = new ArrayList();col.add(1);// 会因为类型无法转换而报错// int i = (Integer)col.get(1);// 泛型的定义在字节码文件中会被去除ArrayList<Integer> col1 = new ArrayList<Integer>();ArrayList<String> col2 = new ArrayList<String>();// col.add(1);//报错,因为类型不匹配,Integer类型的数据无法存入定义了String类型泛型的集合中// col.add(1L);//同上col2.add("abc");String str = col2.get(0);System.out.println("col1和col2的字节码文件是一样的吗?-->"+ col1.getClass().equals(col2.getClass()));// 反射也可以定义泛型Constructor<String> con = String.class.getConstructor();String s = con.newInstance();//printCollection(col2);//定义了限定通配符,传入String类型泛型的集合就会报错printCollection(col1);}//通配符"?"表示任何类型 extends表示必须是Number或者Number的子类才可以,可以使用&限定多个类public static void printCollection(Collection<? extends Number> col){/* * 使用通配符得到的集合不能使用add等与具体类型有关系的方法 * col.add(1)//错误,因为他不知道会匹配到什么类型 * 可以使用与类型无关的方法,如:size(); * * 使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要作用 * 是用做引用,可以调用与参数无关的方法,不能调用与参数有关的方法 */System.out.println(col.size());}}result:
示例2:一般情况下,编写代码能遇到的最复杂的泛型就是在使用Map集合的Map.Entry的时候了,如下述代码,你能看懂了,泛型对你来说也就算基本掌握了
package com.leaf.generic;import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;public class GenericTest1 {public static void main(String[] args) {Map<String,Integer> map = new HashMap<String,Integer>();map.put("zs",20);map.put("laobi", 23);map.put("zxx", 12);Set<Map.Entry<String,Integer>> set = map.entrySet();for(Iterator<Map.Entry<String, Integer>> it = set.iterator();it.hasNext();){Map.Entry<String, Integer> me = it.next();System.out.println(me.getKey()+":"+me.getValue());}Collection<String> col = new ArrayList<String>();col.add("a");col.add("b");col.add("c");addCollection(col, "d");System.out.println(col);String[] strArr = new String[4];copyColToArr(col, strArr);System.out.println(Arrays.asList(strArr));}public static <T> void addCollection(Collection<T> col,T t){col.add(t);}public static <T> T[] copyColToArr(Collection<T> col,T[] arr){Iterator<T> it = col.iterator();int count = 0;while(it.hasNext()){T t = it.next();arr[count] = t;count++;}return arr;}}result:
二、Collections工具类:
示例:
对集合进行排序
package com.leaf.test;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.List;public class CollectionsDemo {public static void main(String[] args) {demo1();}public static void demo1() {List<String> list = new ArrayList<String>();list.add("abcde");list.add("bcda");list.add("cdsfe");list.add("sdfdefdfg");list.add("efdfg");list.add("hasfhfg");// 对list集合进行指定顺序的排序,使用collections提供的方法是按照list集合中的比较器比较,也就是按照字母的ASSIC码表的顺序Collections.sort(list);System.out.println(list);//对集合使用自定义的排序方式,使用集合中字符串的长度进行排序Collections.sort(list, new ComparatorByLength());System.out.println(list);//模拟写一个和collections中提供的方法一样的方法mySort(list, new ComparatorByLength());System.out.println(list);}public static <T> void mySort(List<T> list, Comparator<? super T> comp) {for (int i = 0; i < list.size() - 1; i++) {for (int j = i + 1; j < list.size(); j++) {if (comp.compare(list.get(i), list.get(j)) > 0) {Collections.swap(list, i, j);}}}}}class ComparatorByLength implements Comparator<String> {public int compare(String o1, String o2) {int temp = o1.length() - o2.length();return temp == 0 ? o1.compareTo(o2) : temp;}}result:
注:工具类,内部都是静态方法,直接使用Collections.方法名调用
示例:
package com.leaf.test;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.List;public class CollectionsDemo2 {public static void main(String[] args) {demo1();}public static void demo1() {List<String> list = new ArrayList<String>();list.add("abcde");list.add("bcda");list.add("cdsfe");list.add("sdfdefdfg");list.add("efdfg");list.add("hasfhfg");//寻找:int index = Collections.binarySearch(list, "bcda");System.out.println("index:"+index);//获取长度最长的字符串String max = Collections.max(list);System.out.println("max="+max);}class ComparatorByLength implements Comparator<String> {public int compare(String o1, String o2) {int temp = o1.length() - o2.length();return temp == 0 ? o1.compareTo(o2) : temp;}}}result:
示例:
package com.leaf.test;import java.util.Collections;import java.util.Comparator;import java.util.TreeSet;public class CollectionsDemo3 {public static void main(String[] args) {System.out.println("使用了Collections.reserseOrder(...)");demo3();System.out.println("未使用了Collections.reserseOrder(...)");demo4();}public static void demo4(){TreeSet<String> ts = new TreeSet<String>();ts.add("abc");ts.add("hahaha");ts.add("zzz");ts.add("aa");ts.add("cba");System.out.println(ts);}public static void demo3() {TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder());ts = new TreeSet<String>(Collections.reverseOrder(new ComparatorByLength1()));ts.add("abc");ts.add("hahaha");ts.add("zzz");ts.add("aa");ts.add("cba");System.out.println(ts);}}class ComparatorByLength1 implements Comparator<String> {public int compare(String o1, String o2) {int temp = o1.length() - o2.length();return temp == 0 ? o1.compareTo(o2) : temp;}}result:
示例:
package com.leaf.test;import java.util.ArrayList;import java.util.Collections;import java.util.List;public class CollectionsDemo4 {public static void main(String[] args) {List<String> list = new ArrayList<String>();list.add("abc");list.add("b");list.add("cds");list.add("sdfde");list.add("abc");list.add("ha");System.out.println("-------------------------------------");demo5(list);System.out.println("-------------------------------------");demo6(list);}public static void demo5(List<String> list){//replaceAll方法System.out.println("使用replaceAll方法替换元素");System.out.println("未替换");System.out.println(list);Collections.replaceAll(list, "abc", "wahaha");System.out.println("替换后。。。");System.out.println(list);}public static void demo6(List<String> list){//使用默认随机源随机更改指定列表的序列。所有序列更改发生的可能性都是大致相等的。System.out.println("使用shuffle更改指定列表的序列");System.out.println("更改前");System.out.println(list);Collections.shuffle(list);System.out.println("更改后。。。");System.out.println(list);}}result:
示例:
package com.leaf.test;import java.util.ArrayList;import java.util.List;public class CollectionsDemo5 {/** * 给非同步的集合加锁 * @param args */public static void main(String[] args) {//非同步的集合List list = new ArrayList();//加上锁,变成同步的list = new MyCollections().synList(list);}}class MyCollections{public List synList(List list){return new MyList(list);}private class MyList extends ArrayList{private List list;private final Object lock = new Object();MyList(List list){this.list = list;}public boolean add(Object obj){synchronized(lock){return list.add(obj);}}public boolean remove(Object obj){synchronized(lock){return list.remove(obj);}}}}
三、Arrays工具类
数组的工具类,里面的存放的都是操作数组的静态方法
示例:
package com.leaf.test;import java.util.Arrays;public class ArraysDemo {public static void main(String[] args) {int[] arr = { 10, 5, 6, 8, 2, 9, 2, 3, 4, 5 };//打印出数组System.out.println("-----------打印出数组------------");System.out.println(Arrays.toString(arr));//对数组进行排序System.out.println("-----------数组排序------------");Arrays.sort(arr);System.out.println(Arrays.toString(arr));}}
result:
重点:
List asList(数组)将数组转成集合
好处:
可以使用集合的方法操作数组
弊端:
因为数组的长度是有限的,所以集合的增删操作是不可用的,否则会发送UnsupportedOperationException。
示例:
package com.leaf.test;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class ArraysDemo2 {public static void main(String[] args) {String[] arr = {"abc","qwe","zxc"};List<String> list = new ArrayList<String>();System.out.println(list);list = Arrays.asList(arr);System.out.println(list);System.out.println(list.contains("abc"));}}
result:
示例:由于集合中不能存储基本数据类型,所以当数组中的元素是基本数据类型的时候,那么数据就变成对象存入集合,如果数组中的元素是对象,则是对象变成集合中的元素
package com.leaf.test;import java.util.Arrays;import java.util.List;class ArraysDemo4 {public static void main(String[] args) {int[] arr1 = { 3, 1, 5, 6 };List list1 = Arrays.asList(arr1);System.out.println(list1);Integer[] arr2 = { 3, 1, 5, 6 };List list2 = Arrays.asList(arr2);System.out.println(list2);}}result:
集合转数组:
使用的是Collection接口中的toArray方法
注:集合转成数组,可以对集合中的元素操作的方法进行限定,不允许对其进行增删
toArray方法需要传入一个指定类型的数组
长度该如何定义?
使用集合的size方法得到集合的长度,进行定义数组。
示例:
package com.leaf.test;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class ColToArray {public static void main(String[] args) {List<String> list = new ArrayList<String>();list.add("abc1");list.add("abc2");list.add("abc3");String[] arr = list.toArray(new String[2]);System.out.println(Arrays.toString(arr));}}result:
- 黑马程序员——集合(二)--Collections、Arrays、泛型
- 黑马程序员——集合Collections,集合Arrays
- 黑马程序员——集合——泛型、Collections和Arrays
- 黑马程序员——Java基础---泛型、集合框架工具类:collections和Arrays
- 黑马程序员——Java基础---泛型、集合框架工具类:collections和Arrays
- 黑马程序员——Java基础---泛型、集合框架工具类:collections和Arrays
- 黑马程序员——集合、集合框架工具类(collections和Arrays)和其他对象
- 黑马程序员——集合框架类(Collections、Arrays)
- 黑马程序员———集合(下)[包含Collections和Arrays类]
- 黑马程序员——JAVA基础之Collections和Arrays,数组集合的转换
- 集合—Collections、Arrays
- 黑马程序员—— Collections, Arrays
- 黑马程序员——Java基础---泛型、集合框架工具类:Collections和Arrays、JDK 1.5新特性
- 黑马程序员—collections集合
- 黑马程序员—collections集合
- 黑马程序员--泛型、集合框架工具类:collections和Arrays
- 黑马程序员——JAVA笔记——集合框架5——Collections、Arrays
- 黑马程序员——Java基础--集合框架工具类:Collections、Arrays、其他对象
- Android总结
- NSRunloop 和 NSTimer
- 38.Oracle数据库SQL开发之 对行进行分组
- 《stl源码剖析》剖析
- 【数据结构】串的基本操作
- 黑马程序员——集合——泛型、Collections和Arrays
- python学习笔记(1)
- 39.Oracle数据库SQL开发之 日期和时间的存储与处理——几个简单的存储检索日期
- 2-读书笔记----iOS开发指南:从零基础到App Store上架--iOS视图和控件
- maven之pom.xml配置
- V模型,W模型,H模型介绍
- CvSVM支持向量机应用编程
- 40.Oracle数据库SQL开发之 日期和时间的存储与处理——使用TO_CHAR和TO_DATE
- UVA 10596 Morning Walk(欧拉路)