Java泛型、集合与数组

泛型

Java泛型可以分为泛型类、泛型接口、泛型方法。泛型可以实现参数“任意化”。

interface Info<T>{
  public T getvar();
}

class InfoImpl<T> implements Info<T> {
  private T var;
  public InfoImpl(T var){
    this.setvar(var);
  }
  public void setvar(T var){
    this.var=var;
  }
  public T getvar(){
    return this.var;
  }
  public static void main(String args[]){
    Info<String> i=new InfoImpl<String>("abc");
    System.out.print(i.getvar());
  }
} 

子类的定义中可以声明泛型类型,也可以直接指定具体的类型。

interface Info<T>{
  public T getvar();
}

class InfoImpl implements Info<String> {
  private String var;
  public InfoImpl(String var){
    this.setvar(var);
  }
  public void setvar(String var){
    this.var=var;
  }
  public String getvar(){
    return this.var;
  }
  public static void main(String args[]){
    Info i=new InfoImpl("abc");
    System.out.print(i.getvar());
  }
} 

泛型方法中可以定义泛型参数。

class Demo{
  public <T> T fun(T t){
    return t;
  }
  public static void main(String args[]){
    Demo d=new Demo();
    String str=d.fun("abc");
    int i=d.fun(1);
  }  
}

泛型类本身可以当做参数传入或返回。

class Info<T extends Number>{  //指定上限,只能是数字类型
  private T var;
  public void setvar(T var){
    this.var=var;
  }
  public T getvar(){
    return this.var;
  }
}

public class test{
  public static void main(String args[]){
    Info<Integer> i=fun(1);
    Info<Integer> j=fun(2);
    //如果i和j的泛型类型不统一,则add方法会报错
    add(i,j);
  }  
  public static <T extends Number> Info<T> fun(T var){
    Info<T> temp=new Info<T>();
    temp.setvar(var);
    return temp;
  }
  public static <T extends Number> void add(Info<T> i1,Info<T> i2){
    System.out.print(i1.getvar()+" "+i2.getvar());
    //不能直接用i1.getvar()+i2.getvar(),因为+不能用在T和T之间(就算T是Integer)
  }
}

泛型提高了代码的复用性,减少了工作量。

同时泛型提高了Java程序的类型安全,使用泛型可以使编译器知道变量的类型限制,进而可以在更高程度上验证类型假设。同时可以消除源代码中的许多强制类型转换,减小出错的可能。

Collection集合

Collection是最基本的集合接口,一个Collection代表一组对象,也就是Collection的元素。一些Collection允许相同的元素而另一些不行,一些能排序而另一些不行。Java不提供直接继承自Collection的类,而是提供继承自Collection的子接口的类,比如List和Set.
所有实现Collection接口的类都必须提供两个标准的构造函数:
(1)无参数的构造函数用于创建一个空的Collection
(2)有一个Collection参数的构造函数用于clone这个Collection
如何遍历Collection中的每一个元素?
不论Collection的实际类型如何,它都支持一个iterator()方法,该方法返回一个迭代子,可以逐一访问Collection中的每一个元素。Iterator还支持一个remove()方法.

Iterator it=collection.iterator();
while (it.hasNext()){
  String str=it.next();
  if (str.equals("abc"))
    it.remove();
}

Collection没有实现Clone和Serializable接口。

Collections是针对集合类的一个帮助类,提供一系列静态方法实现对集合的搜索、排序等操作,不要与Collection混淆。

List集合

List是有序的Collection,能够精准控制每一个元素插入的位置。用户能够使用索引来访问List中的元素,List中允许有相同的元素。List还提供一个listIterator()方法,和标准的Iterator接口相比,它多了一些add(),set()之类的方法,允许添加、设定元素,还能向前或者向后遍历。

1.LinkedList类

LinkedList类提供额外的get(),remove(),add(),set()方法,这些操作使得LinkedList可被用作堆栈、队列等数据结构。

2.ArrayList类

ArrayList实现了可变大小的数组。提供的方法和LinkedList几乎一致。在实际使用中经常用到。

3.Vector类

Vector非常类似ArrayList,但是Vector是同步的。而上面两种List结构是异步的。

4.Stack类

Stack继承自Vector,实现一个后进先出的堆栈。Stack提供5个额外的方法,除了push(),pop(),还有peek()得到栈顶元素,empty()测试是否为空,search()检测一个元素在堆栈中的位置。

List集合的遍历

以下列举三种List集合的遍历方法。

(1)for循环,借助size()方法

for (int i=0;i<list.size();i++){
  String s=list.get(i);
  System.out.println(s);
}

(2)使用foreach遍历List

for (String s:list){
  System.out.println(s);
}

(3)使用迭代器遍历

Iterator<String> it=list.iterator();
while (it.hasNext()){
  String s=it.next();
  System.out.println(s);
}

Set集合

Set是一种不包含重复元素的Collection。Set最多有一个null元素。

要小心操作可变对象,如果一个Set中的可变元素改变自身状态导致Set中包含两个相同的元素,将会出现一些问题。

调用add()方法时会返回一个boolean,如果添加失败,会返回false。

1.HashSet

HashSet中的元素需要实现hashCode()和equals()方法。

2.TreeSet

TreeSet中的元素需要实现Comparable接口。

TreeSet可以实现自动排序。

Map集合

Map没有继承Collection接口,Map提供key到value的映射。一个Map中不能包含相同的key,每个key只能映射一个value。Map的内容可以被当做是一组key集合、一组value集合或者一组key-value映射。

1.HashTable类

HashTable继承Map接口,任何不是null的对象都可以作为key或者value。HashTable是同步的。

添加数据使用put(key,value),取出数据使用get(key)。

由于作为key的对象将计算hash函数来确定value的位置,因此任何作为key的对象都必须实现hashCode()和equals()方法。

2.HashMap类

HashMap和HashTable类似,不同之处在于HashMap是不同步的,并且允许null作为key和value。

因此在HashMap中,不能用get()方法来判断是否存在某个键,应该用containsKey()来判断。

有趣的是,HashMap的length总是2的幂次方,这和存储机制有关。

3.WeakHashMap类

WeakHashMap是HashMap的改进,它对key进行“弱引用”,如果一个key不再被外部引用,那么该key会被GC回收。

4.TreeMap类

TreeMap的key要求实现Comparable接口,实现基于红黑树结构,迭代时默认按照key值升序排序。

通配符

1.<? extends T>,确保类型必须是T的子类,用来安全地访问数据;

2.<? super T>,确保类型必须是T的父类,用来安全地写入数据;

3.<?>,它可以被任意类型替代,被称为无限定通配符。

extends和无限定通配符不能安全地写入,因为限定之后类型不确定。

List<? super Number> list1=new Arraylist<>();
list1.add(1);//ok
List<? extends Number> list2=new Arraylist<>();
list2.add(1);//报错

数组

数组的声明:

int[] ar1=new int[100];
int[][] ar2=new int[10][10];
int[][] ar3={
   
   {1,2},{3,4,5,6},{7,8,9}};

数组没有length()方法,只有length属性。
数组的排序:

int[] arr={32,43,542,12,432,54};
Arrays.sort(arr);

最好不要用泛型构造数组,下面的代码是不会被编译器通过的。

T arr=new T[100];

要使用泛型时,应用ArrayList代替。

猜你喜欢

转载自blog.csdn.net/dxy18861848756/article/details/113535953