黑马程序员——Java基础---泛型、集合框架工具类:Collections和Arrays、JDK 1.5新特性

时间:2023-02-24 23:25:41

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

第一部分 泛型
泛型:广泛的类型。就是给对象指定数据类型的安全机制。泛型是JDK1.5 版本以后出现的新特性。用于解决数据的安全问题。是一个安全机制。

好处:

1、将运行时期出现问题 ClassCastException,转移到了编译时期。防便于程序员解决问题。让运行时问题减少,提高安全。

2、避免了强制转换的麻烦。

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

泛型又可以细分为:

1、泛型集合

2、泛型类

3、泛型接口

4、高级泛型

一、泛型集合

在使用java提供的对象时,什么时候写泛型呢?通常在集合框架中很常见。只要见到<>就是定义泛型。其实<>就是用来接收数据类型的。当使用集合时,将集合中要存储的数据类型作为参数传递到<>尖括号中即可。

1)Demo:

    ArrayList<String> al = new ArrayList<String>();//加了“ <> ”。就表示泛型结构,为了定义容器的数据类型,减少出错。 
al.add("java01");
al.add("java02");
al.add("java04");
al.add(2,"java03");
ListIterator<String> li = al.listIterator();
//指定迭代器的数据类型
while (li.hasNext()){
String str = li.next();//这时候就不需要强转了,避免了强制转换的麻烦
if(obj.equals("java02")){
// li.set("java002");//修改操作
// li.remove();//删除操作
}
System.out.println(str);//
}

二、泛型类,泛型方法和泛型接口

1) 什么时候定义泛型类?当类中需要操作的引用数据类型不确定的时候,早期定义 Object 来完成扩展,现在定义泛型来完成扩展。

2) 泛型类定义的泛型在整个类中有效。如果被方法使用,那么泛型类的对象要明确操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。

3) 特殊之处:

静态不可以访问类上定义的泛型。

如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法中。

4) 定义泛型类:

1、可以定义泛型类:class DemoGe< T>

2、可以定义泛型方法:public < S> void show(S s)

3、可以同时定义泛型类和泛型方法。

5) Demo :

package fuxi1;

/**
*
*@author XiaLei
*/

public class Day15Test3 {

public static void main(String[] args) {

}

}
class FanXin<T>{//定义泛型类
public void show(T t){
System.out.println("show");
}
public void run(T t){
System.out.println("run");
}
/*
* 如果不定义泛型类,那么就需要在每一个方法后面传入具体参数,较为麻烦。例如
* public void show(String s){}
* public void run(String s){}
* 简化书写的同时,也出现了弊端,即泛型类一旦明确了类型,则所有的方法都要使用该类型。
*/

public <W> void print(W w){//泛型类中也可以定义泛型方法。

}
public static <W> void speak(){//静态方法不可以访问类上定义的泛型,因为类上的泛型必须要通过创建对象后才能实现,而静态加载出现在对象之前。
//另外注意泛型放在返回值类型前面。

}
}
class FanXinDemo{
public <T> void show(T t){//为了避免泛型类的以上弊端,我们可以定义泛型方法。
System.out.println("show");
}
public <T> void run(T t){
System.out.println("run");
}
}

三、高级泛型
当传入的类型不确定时,可以使用通配符?。也可以理解为占位符。使用通配符的好处是可以不用明确传入的类型,这样在使用泛型类或者泛型方法时,提高了扩展性。

Demo:

package fuxi1;

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

/**
* 泛型限定:用于泛型拓展。
* ? 通配符,也可以理解为占位符。
* ?extends E:可以接受E或者E的子类。上限。
* ?super E:可以接受E或者E的父类。下限。
*@author XiaLei
*/

public class Day15Test4 {

public static void main(String[] args) {

TreeSet<Student> ts = new TreeSet<Student>(new MyLock());
ts.add(new Student("java01"));
ts.add(new Student("java08"));
ts.add(new Student("java00"));
ts.add(new Student("java05"));

TreeSet<GoodStudent> ts1 = new TreeSet<GoodStudent>(new MyLock());
ts1.add(new GoodStudent("java--01"));
ts1.add(new GoodStudent("java--08"));
ts1.add(new GoodStudent("java--00"));
ts1.add(new GoodStudent("java--05"));
// for(Iterator<Student> it = ts.iterator();it.hasNext();){
// System.out.println(it.next().getName());
// }
// for(Iterator<GoodStudent> it = ts1.iterator();it.hasNext();){//书写很麻烦
// System.out.println(it.next().getName());
// }
print(ts);
print(ts1);//定义一个打印方法
}
public static void print(TreeSet<? extends Student> ts){//利用泛型限定简化了书写,利于程序后期扩展。
for(Iterator<? extends Student> it = ts.iterator();it.hasNext();){
System.out.println(it.next().getName());
}
}
}
class Student{
String name;

public Student(String name) {
super();
this.name = name;
}
public String getName(){
return name;
}
}
class GoodStudent extends Student{
public GoodStudent(String name) {
super(name);
}
public String getName(){
return name;
}
}
class MyLock implements Comparator<Student>{//<? super >
public int compare(Student s1,Student s2){
return s1.getName().compareTo(s2.getName());
}
}

第二部分 Collections和Arrays

一、Collections

1)常用方法:

1、sort 方法:给 list 集合排序,用 sort 方法。

2、max 方法:取 list 集合中的最大值。用 max 方法。

demo:

package fuxi1;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
* 集合框架工具类
* 需求:利用Collections工具类给List集合排序,以及求最大值等等。
* 思路:Collections的sort方法就是专门给List集合排序的,如果需要指定比较方法可以创建比较器。
* max方法则是给出最大值,同样也可以加比较器。
*@author XiaLei
*/

public class Day17Test1 {

public static void main(String[] args) {

List<String> list = new ArrayList<String>();
list.add("fdsa");
list.add("fda");
list.add("s");
list.add("ss");
list.add("adfss");
// Collections.sort(list);//按照字符串自然顺序排序。
// System.out.println(list);
Collections.sort(list,new StrLenthCom());//创建比较器,按照字符串长度排序。
System.out.println(list);
// String max = Collections.max(list,new StrLenthCom());//创建比较器,按照字符串长度求最大值。
// System.out.println(max);
int index = Collections.binarySearch(list, "s",new StrLenthCom());//二分查找,如果元素不在则返回-(应插入位置角标)-1;
System.out.println(index);
}

}
class StrLenthCom implements Comparator<String>{
public int compare(String s1,String s2){
if(s1.length()>s2.length())
return 1;
if(s1.length()<s2.length())
return -1;
else
return s1.compareTo(s2);
}
}

3、binarySearch:查询的字符串在集合中是否存在。返回 -1 ,表示不存在;返回 0 ,则存在。

4、fill :将list集合所有元素替换成指定元素。

fill练习:

package fuxi1;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* 需求:利用集合框架工具类的fill方法给集合中部分元素替换成指定元素。
* 思路:利用List集合subList方法,查询集合部分元素并替换。
*@author XiaLei
*/

public class Day17Test2 {

public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("fdsa");
list.add("fda");
list.add("s");
list.add("ss");
list.add("adfss");
// Collections.fill(list, "hah");
// System.out.println(list);
myFill(list,1,2);//改变部分元素。
System.out.println(list);
Collections.replaceAll(list, "s", "x");//替换
System.out.println(list);
Collections.reverse(list);//反转
System.out.println(list);
}
public static List<String> myFill(List<String> list,int start,int end){

List<String> list1 =list.subList(start, end);
Collections.fill(list1, "haha");
return list;
}
}

打印结果:
黑马程序员——Java基础---泛型、集合框架工具类:Collections和Arrays、JDK 1.5新特性

5、reverseOrder :强行逆转比较器。
demo:

package fuxi1;

import java.util.Collections;
import java.util.Iterator;
import java.util.TreeSet;

/**
*
*@author XiaLei
*/

public class Day17Test3 {

public static void main(String[] args) {

TreeSet<String> ts = new TreeSet<String>(Collections.reverseOrder(new StrLenthCom()));//强行逆转比较器,可以实现自然排序的反转,也可以实现自定义比较器的反转。
//这种功能一定要记住~
ts.add("aaaa");
ts.add("bb");
ts.add("c");
ts.add("dxaio");
for (Iterator<String> it = ts.iterator(); it.hasNext();){
System.out.println(it.next());
}
}

}
/*之前定义过的比较器,拿来演示
class StrLenthCom implements Comparator<String>{
public int compare(String s1,String s2){
if(s1.length()>s2.length())
return 1;
if(s1.length()<s2.length())
return -1;
else
return s1.compareTo(s2);
}
}
*/

6、shuffle :随机排序。

7、swap :交换位置。
demo:

package fuxi1;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
*
*@author XiaLei
*/

public class Day17Test4 {

public static void main(String[] args) {

List<String> list = new ArrayList<String>();
list.add("fdsa");
list.add("fda");
list.add("s");
list.add("ss");
list.add("adfss");
Collections.swap(list, 1, 4);//换位。
System.out.println(list);
Collections.shuffle(list);//随机排序。
System.out.println(list);
}

}

二、Arrays

Arrays是用于操作数组的工具类。
1)将数组转换为集合
注意:
a、将数组转换成集合,不可使用集合的增删方法,因为数组的长度是固定的。如果进行增删操作,则会产生UnsupportedOperationException的编译异常。
b、如果数组中的元素都是对象,则变成集合时,数组中的元素就直接转为集合中的元素。
c、如果数组中的元素都是基本数据类型,那么会将该数组作为集合中的元素存在。

好处:可以使用集合的思想和方法来操作数组中的元素。

2)集合变数组
指定类型的数组到底要定义多长呢?
当指定类型的数组长度小于了集合的size,那么该方法内部会创建一个新的数组。长度为集合的size。
当指定类型的数组长度大于了集合的size,就不会新创建了数组。而是使用传递进来的数组。
所以创建一个刚刚好的数组最优。

好处: 可以限定对元素的操作,不可以进行增删了。

第三部分 JDK 1.5的新特性

一、静态导入

1、当类名重名时。需要指定具体的包名

2、当方法重名时。指定具备所属的对象或者类。

二、方法的可变参数

1) 使用注意:可变参数,一定要定义在参数列表的后面。

2) 可变参数传递的使用方式:其实就是上一种数组的参数简写形式,不用每次都动手的建立数组对象,只要将操作的元素作为参数传递即可,隐式的将这些参数封装成了数组。

3) 可变参数的写法:public static void show2(String s,int…arr){}

三、高级 for 循环

1)格式:

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

}

2)for 对集合的遍历,只能获取元素,但是不能对集合进行操作。迭代器除了对集合进行遍历,还能进行 remove 集合中元素的动作。如果是用 ListIterator,还可以在遍历过程中对集合进行增删改查的动作。

3)高级 for 循环的局限性:高级 for 有一个局限性,必须有被遍历的目标。

4)建议:在遍历数组的时候,还是希望使用传统的 for ,因为传统 for 可以定义脚标。高级for:只能对集合中的数据取出,不能做到修改集合中的元素,即使是赋值也没办法。

Demo:

package fuxi1;

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
* 演示高级for循环。
* 反思:事实上在写博客的时候,我已经是在复习了。高级for也已经用过很多次了,然而在前面的复习中,尤其是集合框架这章,
* 用了很多的迭代器进行打印,完全忘了用高级for循环,这就说明了之前学习的不认真,希望自己能够更加努力!
*@author XiaLei
*/

public class Day17Test5 {

public static void main(String[] args) {

TreeMap<Integer,String> tm = new TreeMap<Integer,String>();
tm.put(1, "java01");
tm.put(2, "java02");
tm.put(3, "java03");
tm.put(4, "java04");
//KaySet方式的高级for循环
Set<Integer> s = tm.keySet();
for(Integer i : s){
System.out.println(i+":"+tm.get(i));
}
//entrySet方式的高级for循环
for(Map.Entry<Integer,String> me : tm.entrySet()){
System.out.println(me.getKey()+"="+me.getValue());
}
}
}

四、JDK 1.5 自动装箱与拆箱

1)Integer i = 5;//自动装箱new Integer(5);

2)i = i+2; //i进行自动拆箱,变成了 int 类型,再和 2 相加,再进行装箱赋值给 i 。

3)byte范围是-128~127之间,所以Integer m,n = 128;已经超出byte范围,所以虽然看似相同,其实他们指向了两个不同的 Integer 对象。

总结
本章知识比较零碎,很多内容容易忽视,比如Collections里的reverseOrder强行逆转比较器方法,这些内容方法都是非常实用的方法,掌握它们有时候会让代码精简很多。所以任何的知识点都要引起重视,一次记不住争取第二次就能记住。