API-集合框架(4)-泛型
来源:互联网 发布:p2p线上平台软件 编辑:程序博客网 时间:2024/06/11 09:13
为了让集合使用更安全,问题:什么类型的元素都可以存储。导致取出时,如果出现强转就会引发运行时异常ClassCastException能不能在创建集合时,就明确容器中的元素的类型。如同数组一样。目的是为了更安全。JDK1.5以后,出现了解决方案,使用容器时,必须明确容器中元素的类型。这种机制:称之为:泛型。体现<数据类型>,不是很难理解,<>也是括号,往括号里写东西其实就是在传递参数。泛型:1,安全机制。 2,将运行时期的ClassCastException,转移到了编译时期变成了编译失败。3,泛型技术,是给编译器使用的技术。4,避免了强转的麻烦。
泛型概述
import java.util.ArrayList;import java.util.Iterator;import java.util.List;public class GenericDemo { public static void main(String[] args) { /* * 为了让集合使用更安全, * 问题:什么类型的元素都可以存储。导致取出时,如果出现强转就会引发运行时异常ClassCastException * 能不能在创建集合时,就明确容器中的元素的类型。如同数组一样。 * 目的是为了更安全。 * JDK1.5以后,出现了解决方案,使用容器时,必须明确容器中元素的类型。 * 这种机制:称之为:泛型。 * 体现<数据类型>,不是很难理解,<>也是括号,往括号里写东西其实就是在传递参数。 * 泛型: * 1,安全机制。 * 2,将运行时期的ClassCastException,转移到了编译时期变成了编译失败。 * 3,泛型技术,是给编译器使用的技术。 * 4,避免了强转的麻烦。 */ //int[] arr =new int[8]; //创建集合时,直接在集合上明确要存储的元素的类型 List<String> list=new ArrayList<String>(); list.add("abc");// list.add(6);//只要不是指定类型的对象,编译器检查会报错,这样将允许时的问题转移到编译时期。 for (Iterator it = list.iterator(); it.hasNext();) {/* Object object = (Object) it.next(); System.out.println(object);*/ //想要打印字符串的长度 String str =(String)it.next(); System.out.println(str.length()); } }}
泛型类的使用
import java.util.Iterator;import java.util.LinkedList;public class GenericDemo2 { public static void main(String[] args) {/* Tool t =new Tool(); t.setObject(6); String s= (String)t.getObject(); System.out.println(s);*/ Tool<String> t =new Tool<String>();// t.setObject(6);//只要类型错误,编译失败,避免了运行时类型转换异常 String s =t.getObject();//省去了强转的麻烦 System.out.println(s); Queue<String> queue =new Queue<String>(); queue.myAdd("abc1"); queue.myAdd("abc2"); queue.myAdd("abc3");// queue.myAdd(1);//只要类型错误,编译失败,避免了运行时类型转换异常 while(!queue.isNull()){ System.out.println(queue.myGet()); } }}/* jdk1.5有了新技术,泛型,改成如下这样。 类中操作的对象确定不?不确定,用Object,需要转型,运行容易出异常 在定义时,就将不确定的对象的类型,定义成参数,由使用该类的调用者来传递对象类型。 */class Tool<Q>{//将泛型定义在类上,泛型类。 private Q object; public Q getObject() { return object; } public void setObject(Q object) { this.object = object; }}class Queue<E>{ //封装了一个链表数据结构。 private LinkedList<E> link; /* * 队列初始化时。对链表对象初始化 */ Queue(){ link =new LinkedList<E>(); } /** * 队列的添加元素功能 */ public void myAdd(E obj){ //内部使用的就是链表的方法。 link.addFirst(obj); } /** * 队列的获取方法 */ public E myGet(){ return link.removeLast(); } /** * 判断队列中元素是否空,没有元素就为true。 */ public boolean isNull() { return link.isEmpty(); }}//定义一个工具对象进行操作,比如设置和获取。可以对任意对象进行操作,对共性类型Object操作。//但是提升为了Object,想要使用特有内容,需要向下转型,容易引发ClassCastException/*class Tool{ private Object object; public Object getObject() { return object; } public void setObject(Object object) { this.object = object; }}*/
泛型方法的使用
public class GenericDemo3 { public static void main(String[] args) { Util<String> util = new Util<String>(); util.show("hehe");// util.print(5); Util<Integer> util2 = new Util<Integer>(); Util.print(5); util2.show("hehe"); }}class Util<W>{ //当方法要操作的类型不确定和类上的泛型不一定一样。这时可以将泛型定义在方法上。 public <Q> void show(Q q){//泛型方法 System.out.println("show:"+q); } public static<E> void print(E e){//记住:如果方法是静态,还需要使用泛型,那么泛型必须定义在方法上。 System.out.println("print:"+e); } public void method(W w){ }}
泛型接口的使用
public class GenericDemo4 { public static void main(String[] args) { new InterImpl<String>().show("hehe"); }}//泛型接口。interface Inter<E>{ void show(E e);}/*class InterImpl implements Inter<String>{ public void show(String e){}}*/class InterImpl<T> implements Inter<T>{ @Override public void show(T e) { }}
People
public class Person { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; }}
Student
public class Student extends Person { public Student() { super(); // TODO Auto-generated constructor stub } public Student(String name, int age) { super(name, age); // TODO Auto-generated constructor stub } @Override public String toString() { return "Student [Name=" + getName() + ", Age=" + getAge() + "]"; } }
Worker
public class Worker extends Person { public Worker() { super(); // TODO Auto-generated constructor stub } public Worker(String name, int age) { super(name, age); // TODO Auto-generated constructor stub } @Override public String toString() { return "Worker [Name=" + getName() + ", Age=" + getAge() + "]"; }}
泛型通配符的使用
import java.util.ArrayList;import java.util.Collection;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Set;import domain.Student;public class GenericDemo5 { public static void main(String[] args) { Set<Student> list =new HashSet<Student>(); list.add(new Student("lisi1",11)); list.add(new Student("lisi2",12)); list.add(new Student("lisi3",13)); printList(list); List<String> list2 =new ArrayList<String>(); list2.add("lisi11"); list2.add("lisi22"); list2.add("lisi33"); printList(list2); } /* * 打印集合中的元素。 * * 当使用泛型或者接口时,传递的具体的类型不确定,可以通过通配符(?)表示。 */ private static void printList(Collection<?> list2) { for (Iterator<?> it = list2.iterator(); it.hasNext();) { System.out.println(it.next().toString()); } }}
泛型的限定的使用
import java.util.ArrayList;import java.util.Collection;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Set;import domain.Person;import domain.Student;import domain.Worker;public class GenericDemo6 { public static void main(String[] args) { Set<Student> list1 =new HashSet<Student>(); list1.add(new Student("lisi1",11)); list1.add(new Student("lisi2",12)); list1.add(new Student("lisi3",13)); printList(list1); List<Worker> list2 =new ArrayList<Worker>(); list2.add(new Worker("lisi11",11)); list2.add(new Worker("lisi22",12)); list2.add(new Worker("lisi33",13)); printList(list2); } /* * 打印集合中的元素。 * * 当使用泛型或者接口时,传递的具体的类型不确定,可以通过通配符(?)表示。 * 如果想要对被打印的集合中的元素类型进行限定,只要指定的一些类型,进行打印。 * 使用泛型的限定。 * * 只需要打印学生和工人的集合,找到学生和工人的共性类型Person. * ? extends Person:接收Person类型或者Person的子类型。上限。 * 总结: * ? extends E:接收E类型或者E的子类型。上限 * ? Super E:接收E类型或者E的父类型。下线 */ private static void printList(Collection<? extends Person> list) { for (Iterator<? extends Person> it = list.iterator(); it.hasNext();) { System.out.println(it.next().toString()); } }}
通配符在api中的体现和使用
import java.util.ArrayList;import java.util.Collection;import java.util.HashSet;import java.util.Iterator;import java.util.List;import java.util.Set;import domain.Student;public class GenericDemo7 { public static void main(String[] args) { /* * 通配符? 在api中的体现。 * * Collection接口: boolean containsAll(Collection<?> c) */ Collection<String> c1 = new ArrayList<String>(); c1.add("haha"); c1.add("hehe"); Collection<Integer> c2 = new ArrayList<Integer>(); c2.add(4); c2.add(5); boolean b = c1.containsAll(c2);//了解 containAll源码内判断是否包含的依据。依据是equals方法。 //public boolean equals(Object obj) "abc".equals(5); System.out.println("b="+b); }}/* * class Collection<E> * { * public boolean containsAll(Collection<?> c){ * } * } */
泛型上限在api中的体现和使用
import java.util.ArrayList;import java.util.Collection;import java.util.Iterator;import java.util.TreeSet;import cn.itcast.domain.Person;import cn.itcast.domain.Student;public class GenericDemo8 { public static void main(String[] args) { /* * 泛型的限定在api中的使用。上限的体现。 * TreeSet(Collection<? extends E> c) * * */ //创建一个Collection. Collection<Student> c = new ArrayList<Student>(); c.add(new Student("wangcai1",26)); c.add(new Student("wangcai2",29)); //TreeSet集合在创建时,就将c中的存储到Treeset集合。 TreeSet<Person> ts = new TreeSet<Person>(c); ts.add(new Person("lisi",20)); for (Iterator<Person> it = ts.iterator(); it.hasNext();) { Person person = it.next(); System.out.println(person); } }}/* * class TreeSet<E>{ * TreeSet(Collection<? extends E> c){} */
泛型下限在api中的体现和使用
import java.util.Comparator;import java.util.Iterator;import java.util.TreeSet;import cn.itcast.domain.Person;import cn.itcast.domain.Student;import cn.itcast.domain.Worker;public class GenericDemo9 { public static void main(String[] args) { /* * 泛型的限定在api中的使用。下限的体现。 * TreeSet(Comparator<? super E> comparator) * * */ //创建一个集合存储的是学生对象。想要按照姓名排序。 TreeSet<Student> ts = new TreeSet<Student>(new ComparatorByName()); ts.add(new Student("abc",26)); ts.add(new Student("aaa",29)); ts.add(new Student("lisi",20)); for (Iterator<Student> it = ts.iterator(); it.hasNext();) { Student student = it.next(); System.out.println(student); } //让工人按照姓名排序。 TreeSet<Worker> ts2 = new TreeSet<Worker>(new ComparatorByName()); ts2.add(new Worker("abc",26)); ts2.add(new Worker("aaa",29)); ts2.add(new Worker("lisi",20)); for (Iterator<Worker> it = ts2.iterator(); it.hasNext();) { Worker worker = it.next(); System.out.println(worker); } }}class ComparatorByName implements Comparator<Person>{ @Override public int compare(Person o1, Person o2) { int temp = o1.getName().compareTo(o2.getName()); return temp==0? o1.getAge() - o2.getAge() : temp; }}/* * 以下两个比较器,都是通过姓名排序,就是类型不同,一个是student,一个是worker * 既然使用的都是Person的内容,为什么不定义一个Person的比较器。 *//*//定义一个比较器。class ComparatorByName implements Comparator<Student>{ @Override public int compare(Student o1, Student o2) { int temp = o1.getName().compareTo(o2.getName()); return temp==0? o1.getAge() - o2.getAge() : temp; }}//定义一个工人的姓名比较器。class ComparatorByWorkerName implements Comparator<Worker>{ @Override public int compare(Worker o1, Worker o2) { int temp = o1.getName().compareTo(o2.getName()); return temp==0? o1.getAge() - o2.getAge() : temp; }}*//* * class TreeSet<E>{ * TreeSet(Comparator<? super E> c){} */
泛型细节:保证两边泛型值一致
import java.util.ArrayList;import java.util.List;public class GenericDemo10 { /** * @param args */ public static void main(String[] args) {// ArrayList<Dog> al = new ArrayList<Animal>();//使用泛型,要保证左右类型一致。// ArrayList<String> al = new ArrayList<Object>(); List<Integer> list = new ArrayList<Integer>();// show(list); } public static void show(List<String> list){ }}
GenericTest1
对字符串按照长度排序,比较器用匿名内部类完成。想要逆序,只要将o1和o2比,改成o2和o1比。
import java.util.Comparator;import java.util.Iterator;import java.util.Set;import java.util.TreeSet;public class GenericTest { public static void main(String[] args) { // 创建一个唯一性元素的集合要求排序。set --treeset Set<String> set =new TreeSet<String>(new Comparator<String>() { @Override public int compare(String o1, String o2) { int temp =o1.length()-o2.length(); return temp==0?o1.compareTo(o2):temp; } }); //添加元素 set.add("abcd"); set.add("java"); set.add("hello"); for (Iterator<String> it = set.iterator(); it.hasNext();) { String string = it.next(); System.out.println(string); } }}
GenericTest2
获取集合元素最大值,1,指定类型 2,Object类型,3,泛型限定。★★★★★
import java.util.ArrayList;import java.util.Collection;import java.util.Comparator;import java.util.Iterator;import cn.itcast.domain.Student;public class GenericTest2 { public static void main(String[] args) { /* * 案例:获取集合中元素的最大值。 * * 思路: 1,定义变量记录每次比较后较大的值,初始化元素中任意一个。 2,遍历容器 * 3,在遍历中和变量中记录的元素进行比较。并将较大的值记录到变量中。 4,遍历结束,变量中记录的就是最大值。 */ Collection<Student> c1 = new ArrayList<Student>(); c1.add(new Student("xiaoming1", 30)); c1.add(new Student("xiaoming2", 36)); c1.add(new Student("xiaoming3", 22));// c1.add(new Dog()); Student stu = getMax(c1); System.out.println(stu); Collection<String> c2 = new ArrayList<String>(); c2.add("abcd"); c2.add("java"); c2.add("z"); c2.add("nba"); String s = getMax(c2); System.out.println("s="+s); Collection<Dog> c3 = new ArrayList<Dog>();// getMax(c3);//已经做了限定,说明传递的集合中的元素类型必须是Comparable的子类。否则编译失败。 }public static <T extends Comparable<? super T>> T getMax(Collection<? extends T> c,Comparator<? super T> comp){ if(comp==null){ return getMax(c); } Iterator<? extends T> it = c.iterator(); T max = it.next(); while(it.hasNext()){ T temp = it.next(); if(comp.compare(temp, max)>0){ max = temp; } } return max; } // 升级版。要操作的元素的类型确定不?不确定。使用泛型限定。getMax方法接收的集合中的元素无论时什么类型,必须具备自然排序,必须是Comparable的子类。 public static <T extends Comparable<? super T>> T getMax(Collection<? extends T> c){ Iterator<? extends T> it = c.iterator(); T max = it.next(); while(it.hasNext()){ T temp = it.next(); if(temp.compareTo(max)>0){ max = temp; } } return max; } /* //不加泛型时,无法明确集合中的元素时什么类型,为了便于操作用Object public static Object getMax(Collection c1) { // 1,定义变量,记录集合中任意一个元素,Collection集合取出元素的方式只有迭代器。 Iterator it = c1.iterator(); Object max = it.next(); // 2,遍历容器。 while (it.hasNext()) { Object o = it.next(); Comparable temp = (Comparable)o; if (temp.compareTo(max) > 0) { max = temp; } } return max; }*/ /* * //这个功能虽然实现,但是有局限性,因为这个功能只能对存储了Student对象的集合进行最大值的获取。 public static Student * getMax(Collection<Student> c1) { * * //1,定义变量,记录集合中任意一个元素,Collection集合取出元素的方式只有迭代器。 Iterator<Student> it = * c1.iterator(); Student max = it.next(); * * //2,遍历容器。 while(it.hasNext()){ Student temp = it.next(); * * if(temp.compareTo(max) > 0){ max = temp; } } return max; } */}class Dog{}
【作业】
1,Collection和Collections的区别?【面试题】
Collection是集合框架的顶层接口。 下面有两个开发中常用的List 和 Set集合。 根据数据结构的不同,也有了很多的具体子类集合对象。Collections:是集合框架中的用于操作集合的工具类。 提供了很多的静态方法:比如:对list排序,二分查找,比如可以获取最值等。 其中一组可以非同步集合转成同步 集合的方法。
2,对List集合中存储的重复字符串元素,按照长度进行排序。
import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.List;public class Test2 { public static void main(String[] args) { //作业2:List集合中存储的重复字符串元素,按照长度进行排序。 List<String> list = new ArrayList<String>(); list.add("nba"); list.add("abcde"); list.add("nba"); list.add("cctv"); list.add("zz"); list.add("cctv"); list.add("itcast"); Collections.sort(list,new Comparator<String>() { @Override public int compare(String o1, String o2) { int temp = o1.length() - o2.length(); return temp==0?o1.compareTo(o2):temp; } }); for(String str : list){ System.out.println(str); } }}
3,在一个已排序的List集合中插入一个字符串,继续保证这个集合原有排序,问如何获取这个位置。【面试题】
使用到了二分查找。
import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.List;public class Test3 { public static void main(String[] args) {// 3,在一个已排序的List集合中插入一个字符串,继续保证这个集合原有排序,问如何获取这个位置。 List<String> list = new ArrayList<String>(); list.add("nba"); list.add("abcde"); list.add("nba"); list.add("cctv"); list.add("zz"); list.add("cctv"); list.add("itcast"); Collections.sort(list); String key = "haha"; //找一个元素在集合中出现的位置。 int index = Collections.binarySearch(list, key); System.out.println("index="+index); if(index<0){ index = -(index+1); } System.out.println("index="+index); System.out.println(list); list.add(index, key); System.out.println(list); }}
5,一个ArrayList对象alist中存有若干个字符串元素,现欲遍历该ArrayList对象, 删除其中所有值为”abc”的字符串元素
,请问下面的实现正确么?如有问题,
会出现什么问题?如何更正?
int size = alist.size();for(int i = 0; i < size; i++) { if("abc".equals(alist.get(i))) { alist.remove(i); }}
import java.util.ArrayList;import java.util.List;public class Test5 { public static void main(String[] args) {// 5,一个ArrayList对象alist中存有若干个字符串元素,现欲遍历该ArrayList对象,// 删除其中所有值为"abc"的字符串元素,请问下面的实现正确么?如有问题,// 会出现什么问题?如何更正? //1,移除成功会导致集合长度改变, 必须要重新获取size。导致了IndexOutOfBoundsException。 //解决方案:在for循环的条件上,调用size方法。 //2,出现了有些abc没有被删除。那么是因为删除后,角标自增,原角标上的后替换过来的元素没有被判断。 //解决方案:在删除后,要让角标自减,重新判断替换过来的元素。 List<String> list = new ArrayList<String>(); list.add("nba"); list.add("abc"); list.add("abc"); list.add("abc"); list.add("abc"); list.add("cctv"); System.out.println(list);// int size = list.size(); for(int i = 0; i < list.size(); i++) { if("abc".equals(list.get(i))) { list.remove(i);//会改变集合的长度。应该重新获取size。 i--; } } System.out.println(list); }}
Collections工具类
import java.util.ArrayList;import java.util.Collection;import java.util.Collections;import java.util.Comparator;import java.util.List;import cn.itcast.api.c.comparator.ComparatorByLength;public class CollectionsDemo { public static void main(String[] args) { /* * Collections: 集合框架中的用于操作集合对象 工具类。 * 都是静态的工具方法。 * 1,获取Collection最值。 * 2,对List集合排序,也可以二分查找。 * 3,对排序逆序。 * 4,可以将非同步的集合转成同步的集合。 * Xxx synchronizedXxx(Xxx) List synchronizedList(List) */ System.out.println("---------获取最值---------------"); Collection<String> c = new ArrayList<String>(); c.add("haha"); c.add("zz"); c.add("xixii"); c.add("abc"); String max = Collections.max(c,new ComparatorByLength()); System.out.println("max="+max); System.out.println("-----------排序-------------"); List<String> list = new ArrayList<String>(); list.add("hahaha"); list.add("abc"); list.add("xiix"); list.add("z"); list.add("java"); Collections.sort(list,Collections.reverseOrder()); System.out.println(list); }}
Arrays工具类-集合和数组的互转
import java.util.ArrayList;import java.util.Arrays;import java.util.Collection;import java.util.List;public class ArraysDemo { public static void main(String[] args) { /* * Arrays:用于操作数组的工具类。 * 类中定义的都是静态工具方法 * 1,对数组排序。 * 2,二分查找。 * 3,数组复制。 * 4,对两个数组进行元素的比较,判断两个数组是否相同。 * 5,将数组转成字符串。 */ int[] arr = {34,21,67}; System.out.println(Arrays.toString(arr)); //将arr转成list集合。?如果数组中存储的是基本数据类型,那么转成集合,数组对象会作为集合中的元素存在。 //数组中元素时引用数据类型时,转成,数组元素会作为集合元素存在。 List<int[]> list1 = Arrays.asList(arr); System.out.println(list1); String[] strs = {"hah","hehe","xixi"}; boolean b = contains(strs,"hehe"); System.out.println(b); //将数组转成list集合。asList /* * 数组转成集合:就为了使用集合的方法操作数组中的元素。 * 但是不要使用增删等改变长度的方法。add remove 发生UnsupportedOperationException */ List<String> list = Arrays.asList(strs); System.out.println(list.contains("hehe")); System.out.println(list.get(2)); System.out.println(list.indexOf("hehe"));// list.add("java");//UnsupportedOperationException 数组长度的固定的,转成List集合长度也是固定的。 //-------------------集合转成数组--------------------- /* * 为什么集合转成数组呢? * 为了限制对元素的增删操作。 */ Collection<String> c = new ArrayList<String>(); c.add("haha1"); c.add("haha2"); c.add("haha3"); c.add("haha4"); /* * 如果传递的数组的长度小于集合的长度,会创建一个同类型的数组长度为集合的长度。 * 如果传递的数组的长度大于了集合的长度,就会使用这个数组,没有存储元素的位置为null。 * 长度最好直接定义为和集合长度一致。 */ String[] str_arr = c.toArray(new String[c.size()]); System.out.println(Arrays.toString(str_arr)); } public static boolean contains(String[] strs,String key) { for (int i = 0; i < strs.length; i++) { if(strs[i].equals(key)){ return true; } } return false; }}
阅读全文
0 0
- API-集合框架(4)-泛型
- API-集合框架(1)-介绍
- API-集合框架(2)-List
- API-集合框架(3)-Set
- API-集合框架(5)-Map
- javaSE实战--(API)中的集合框架
- API集合框架-LinkedList
- API集合框架--泛型类
- API-集合框架
- 4.3常用对象API-集合框架(Collection,Map,泛型,集合工具类)
- API常用对象--集合类(集合框架)
- 集合框架(泛型)
- API集合框架-Set集合之HashSet
- API集合框架-Set集合之TreeSet
- java集合框架(1)-从api角度分析集合框架的结构
- 黑马程序员——第15天——(API)集合框架(TreeSet,泛型)
- 11.API学习——集合类框架(4)——泛…
- 16-集合框架-01-常用对象API(集合框架-概述)
- 缓存第四篇:在maven项目中使用redis实例
- SpringBoot Jenkins自动构建
- 分享一个香橙派PC2的C语言点亮LED程序
- android常用系统广播
- 配置单臂路由
- API-集合框架(4)-泛型
- 关系并查集 处理关系的方法
- 2017.07.11【NOIP提高组】模拟赛B组
- JavaScript
- new与malloc的区别(1)
- 选择排序(选择排序和堆排序)
- 面向对象编程之static关键字
- C,C++,C#三者区别
- SRM549 Div1Medium MagicalHats