【主要介绍泛型和泛型接口】
1.foreach
foreach是Java5的新特性,特别便于遍历使用,主要增强了for循环,在遍历数组和集合上很方便
foreach是for循环的简化版本,但是foreach是不能完全取代for循环,然而任何foreach都可以修改为for循环,foreach不是一个关键字,主要就是这个格式,每一个for的意思
//foreach的格式
for(元素类型type 元素变量value:遍历对象obj){
引用x的语句;}
2.Lambda表达式
(JDK1.8引入了函数式编程,重点包括函数式接口、lambda表达式、方法引用等);
Lambda表达式:
Lambda表达式简化了匿名内部类的操作方式;
Lambda表达式可以用在两个地方,一种是集合遍历,另一种就是替换匿名内部类(前者基于Itreable接口和Map接口定义的foreEch方法,后者则依据函数式接口)
(我们需要知道集合对象如何使用它进行操作:
语法格式:
集合名称.forEach(实参名->方法名(实参名));
对l1对象进行打印输出的例子:
l1.forEach(ele->System.out.print(ele+" "));
Lis接口 | 元素以线性方式存储,存储与添加的顺序相同,允许空值 |
Map接口 | 以键-值的映射来存储元素,键-值不允许重复 |
Set接口 | 不保证元素的顺序,不允许重复元素 |
3.List接口
允许重复的元素;
允许null值;
元素在集合中的顺序与添加顺序一致;
常用的实现该接口的类:
ArrayList | 动态数组 |
Vector | 向量 |
LinkedList | 链表 |
Stack | 堆栈(LIFO) |
ArrayList/Vector/LinkedList/Stack的区别:
ArrayList和Vector是采用数组方式存储数据,允许直接序号索引元素,但是插入数据要涉及到数组元素移动等内存操作,所以索引数据快、插入数据慢,Vector由于使用了synchronized(线程安全),但是性能上比ArrayList要差;
LinkedList使用双向链表实现存储,按序号索引数据需要进行向前或向后遍历,但是插入数据时只需要记录本项的前后项即可,所以插入速度较快;
Stack是按照堆栈的原理的原理来存储数据,先进后出;
4.Set接口
Set接口不保证元素的顺序,不允许出现重复的元素;
实现Set的接口的类:HashSet、TreeSet;
TreeSet是Set的一种变体,可以实现按照自然顺序排序,在添加元素的时候会自动将其插入到已经有序的元素序列中;
·字符串按照“字典”顺序
·整数按照数字大小的顺序
HashSet和TreeSet的区别:HashSet不保证元素的顺序,而TreeSet可以自然顺序插入添加的元素 |
5.Map接口
使用键-值的承兑映射来储存元素;
键不允许重复;
常用实现Map接口的类:
类名 | null | 元素顺序 | 线程安全 |
HashMap | 允许null键和值 | 不保证元素的顺序 | 线程不安全 |
Hashtable | 不允许有null键和值 | 不保证元素的顺序 | 线程安全 |
TreeMap | 不允许有null键 | 可以按键的自然顺序将值排序 |
两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高一些,我们平时使用若无特殊需求建议使用HashMap |
6.Iterator接口
Iterator接口可以以统一的方式对各种集合元素进行遍历,也称为“迭代器”。它还可以在遍历元素的同时移除元素;
hasNext()方法检测集合中是否还有下一个元素;
next()方法返回集合中的下一个元素;
Iterator()遍历集合元素的语法:
Iterator it = 集合对象名.iterator();
while(it.hasNext()){
Object o = it.next();
System.out.println(o);}
7.Comparable接口
Java.lang包中定义一个比较对象的接口;
提供抽象方法compareTo(),可以对对象进行整体排序;
使用方法:对要进行比较对象的类实现Comparable接口,重写compareTo()方法;
Comparable接口不仅仅用于集合框架,可用于任何需要进行对象比较的场合;
实例:
class Student implements Comparable{ //实现Comparable接口
int id;
String name;
...
public int compareTo(Object obj){ //重写Comparable接口的compareTo方法
Student s = (Student)obj;
return this.id - s.id;
}
...
}
Java.util包中提供的一个对某个对象进行整体排序的比较接口;
提供了compare的比较方法来比较对象;
使用方法:
·定义实现该接口的类,重写compare方法;
·实例化该对象的类;
·把该对象作为Collections.sort()方法的第二个参数;
//实现Comparator接口,比较学生姓名
class NameComp implements Comparator{
//重写compare方法
public int compare(Object o1,Object o2){
Student s1 = (Student)o1;
Student s2 = (Student)o2;
return s1.name.compareTo(s2.name);
}
}
...
public static viod main(String[] args){
...
NameComparator nc = new NmaeCoparator();
Collection.sort(al,nc);
}
...
8.类型安全问题:
任何对象加入集合类之后,自动转变为Object类型,取出时,有时需要进行类型转换,恢复特定的类型
9.什么是泛型(Generics)?
JDK1.5引入的新特定;
在创建集合对象时就规定其允许保存的元素类型,然后由编译器负责检查索要添加元素的合法性。在取元素时就不必再进行强制性的类型转换处理。其实就是将原本不确定的类型参数化。
//例如:定义只能存储字符串的ArrayList集合对象
ArrayList<String> list = new ArrayList<String>();
list.add("Welcome");//编译通过
list.add("Hello");//编译通过
list.add(new Student());//编译错误
for(String s:list){
System.out.println(s);//取出元素时无需进行类型转换
}
10.使用泛型的优点:
保证集合中所有元素的类型数据相同;
从泛型集合中取出元素时无需再做类型转换;
向集合中添加不符合指定类型的数据,编译时会发生错误信息,避免运行时错误的发生;
是原有Java类型体系的扩充,是编译时的保护;
可以提高Java应用程序的安全性、可维护性、可靠性;
11.泛型的向后兼容性:
Java中的泛型是可以向后兼容的,即可以不采用泛型继续沿用过去的做法,如下:
ArrayList list = new ArrayList();
list.add("Welcome");//编译通过
list.add(new Student());//编译通过
想要避免该警告,可以在类的前面使用@SuppressWarnings({"unchecked"})的注解
@SuppressWarnings({"unchecked"})
class Demo{
public static void main(String[] args){
ArrayList list = new ArrayList();
list.add("Welcome");
list.add(new Student());
}
}
12.泛型高级特性---泛型类
类的定义可在类名后面用尖括号括起来一个类型参数,这种由类型参数修饰的类被称为泛型类。泛型类也属于引用类型:
public class Demo<T>{//<T>为参数类型
private T m;
public T getM(){...}
...
}
参数T是一个类型形参,在使用该泛型类时才指定具体类型参数
Demo<String> d = new Demo<String>();
//则T代表String类型
13.泛型高级特性---泛型方法
public<T> T evaluate(T a, T b){ //表示该方法为泛型方法
...
}
实际调用该方法时才确定参数,如:
·evaluate("hello","hello");
·evaluate(new Integer(100),new Integer(300));
·类型参数T也可以添加到其所在的类中,该类就变成泛型类;
14.泛型接口
·Iterator<T>可以在使用迭代器遍历结合元素时无需类型转换;
·Comparable<T>和Comparator<T>其使用和以前一样,只是多了泛型的安全机制;
15.受限的类型参数
·实例化泛型类时,可以将类型参数T的位置用任意的引用类型替代;
·如果要求该类型参数是某一父类的子类时,受限的类型参数可以兼顾通用性和针对性:
public class Point<T extend Number>{
...}//表示该泛型类只可以传递Number类型或其子类
16.使用泛型方法和泛型类
什么时候使用泛型方法呢,而不是泛型类呢?
·添加类型约束只作用于一个方法的多个参数之间、而不涉及到类中的其他方法时,使用泛型方法
·施加类型约束的方法为静态方法,只能将其定义为泛型方法,因为静态方法不能使用其所在类的类型参数
17.类型通配符-1
同一个泛型类与不同的类型参数符合而成的类型之间并不存在继承关系,见以下代码:
class Person{}
class Student extends Person{}
public class GenericDemo3{
public static void main(String[] args){
Vector<Object> v = new Vector<Student>();
}//<Object>与<Student>编译报错:不兼容的类型
}
同一个泛型类与不同的类型参数复合而成的类型之间并不存在继承关系;
18.类型通配符-2
假设刚才的继承关系是合理的,则会出现以下尴尬矛盾的代码:
import java.util.*;
class Person{
String name;
int age;
Person(){}
Person(String name,int age){
this.name=name;
this.age=age;
}
public void printInfo(){
System.out.println(name + "\t" + age);
}
}
class MyClass<T>{
T m;
void set(T m){
this.m = m;
}
}
public class TypeDemo{
public static void main(String[] args){
MyClass<Person> c1 = new MyClass<Person>();
c2.set(new Integer)();
}
}
19.类型通配符-3
·Vector<?>是任何泛型类Vector的父类
·Vector<?>类型的变量在调用方法时有限制---凡是必须知道具体类型参数才能进行的操作均被禁止
如:Vector<?>的对象禁止调用add()方法,但并不等于时“只读”,例如可以执行remove()方法
20.受限制的通配符
1.上限通配符:?extends 类名
类型通配符?之后可以加extends来限制参数类型只能为某个类的子类
public void show(Vector<? extends Number> v)
{}//该类型方法只接受Number类型或其子类的对象的泛型参数
2.下限通配符:?super
下限类型通配符<? super 类名>可以限制参数类型只能为某个类或以某类为父类,允许添加该类的对象,因此该类的子类对象也可以添加