1. 泛型

1.1泛型概述

泛型:是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测倒非的类型
它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数
一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?
顾名思义,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型
这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口

泛型定义格式:

  • <类型>:指定一种类型的格式。这里的类型可以看成是形参
  • <类型1,类型2.…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参
  • 将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型

泛型的好处:

  • 把运行时期的问题提前到了编译期间
  • 避免了强制类型转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package demo_01;

//需求:Collection集合存储字符串并遍历

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class GenericDemo {
public static void main(String[] args) {
//创建集合对象
//Collection c = new ArrayList();
Collection<String> c = new ArrayList<String>();

//添加元素
c.add("hello");
c.add("java");
//c.add(100); 把运行时期的问题提前到了编译期间(数据类型报错)

//遍历
//Iterator it = c.iterator();
Iterator<String> it = c.iterator();
while (it.hasNext()){
/*Object obj = it.next();
System.out.println(obj);*/
/*
String s = (String)it.next(); //ClassCastException抛出表示代码尝试将对象转换为不属于实例的子类
System.out.println(s);
*/
String n = it.next();
System.out.println(n);
}
}
}
//运行结果
hello
java

1.2 泛型类

泛型类的定义格式:

  • 格式:修饰符 class 类名<类型>{ }
  • 范例:public class Generic{ }
  • 此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
1
2
3
4
5
6
7
8
9
10
11
12
13
package demo_02;

public class Generic<T> {
private T t;

public T getT(){
return t;
}

public void setT(T t) {
this.t = t;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
//1.创建泛型类
package demo_02;

public class Generic<T> {
private T t;

public T getT(){
return t;
}

public void setT(T t) {
this.t = t;
}
}

//2.测试类
package demo_02;

public class GenericDemo {
public static void main(String[] args) {
//创建泛型类的对象时说明对象类型 Generic<String>
Generic<String> g1 = new Generic<String>();
g1.setT("hello");
System.out.println(g1.getT());

Generic<Integer> g2 = new Generic<Integer>();
g2.setT(18);
System.out.println(g2.getT());

Generic<Boolean> g3 = new Generic<Boolean>();
g3.setT(true);
System.out.println(g3.getT());
}
}
//运行结果
hello
18
true

1.3 泛型方法

泛型方法的定义格式:

  • 格式:修饰符<类型>返回值类型方法名类型变量名){}
  • 范例:public void show(T t){ }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
//1.
package demo_03;

//1.普通类
/*public class Generic {
public void show(String s) {
System.out.println(s);
}

public void show(int i) {
System.out.println(i);
}

public void show(Boolean b) {
System.out.println(b);
}
}*/

//2.泛型类改进
/*public class Generic<T> {
public <T> void show(T t){
System.out.println(t);
}
}*/

//3.泛型方法改进
public class Generic {
public <T> void show(T t){
System.out.println(t);
}
}

//2.c
package demo_03;

public class GenericDemo {
public static void main(String[] args) {
//1.普通类
/* Generic g = new Generic();
g.show(18);
g.show("hello");
g.show(true);*/

//2.泛型类
/*Generic<String> g1 = new Generic<String>();
g1.show("java");
Generic<Integer> g2 = new Generic<Integer>();
g2.show(18);
Generic<Boolean> g3 = new Generic<Boolean>();
g3.show(true);*/

//3.泛型方法改进
Generic g = new Generic();
g.show("hello");
g.show(18);
g.show(true);
}
}
//运行结果
hello
18
true

1.4 泛型接口

泛型接口的定义格式:

  • 格式:修饰符 interface 接口名<类型> {}
  • 范例:public interface Generic{}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//1.创建接口
package demo_04;

public interface Generic<T> {
void show(T t);
}

//2.接口实现类
package demo_04;

public class GenericImpl<T> implements Generic<T>{
@Override
public void show(T t) {
System.out.println(t);
}
}

//3.测试类
package demo_04;

public class GenericDemo {
public static void main(String[] args) {
Generic<String> g1 = new GenericImpl<String>();
g1.show("张三");

Generic<Integer> g2 = new GenericImpl<Integer>();
g2.show(18);
}
}
//运行结果
张三
18

1.5 类型通配符

为了表示各种泛型List的父类,可以使用类型通配符

  • 类型通配符:**<?>**
  • List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
  • 这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中

如果说我们不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限

  • 类型通配符上限:**<?extends类型>**
  • List<? extends Number>:它表示的类型是Number或者其子类型

除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限

  • 类型通配符下限:**<?super类型>**
  • List<?super Number>::它表示的类型是Number?或者其父类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package demo_05;

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

/*
- 类型通配符上限:<?extends类型>
- List<? extends Number>:它表示的类型是Number或者其子类型

- 类型通配符下限:<?super类型>
- List<?super Number>::它表示的类型是Number?或者其父类型
*/
public class GenericDemo {
public static void main(String[] args) {
//类型通配符
List<?> list1 = new ArrayList<String>();
List<?> list2 = new ArrayList<Integer>();
List<?> list3 = new ArrayList<Number>();
System.out.println("-------------");

//类型通配符上限
//List<? extends Number> list4 = new ArrayList<Object>(); 保错
List<? extends Number> list5 = new ArrayList<Integer>();
List<? extends Number> list6 = new ArrayList<Number>();
System.out.println("-------------");

//通配符下限
List<? super Number> listb7 = new ArrayList<Object>();
List<? super Number> listb8 = new ArrayList<Number>();
// List<? super Number> listb9 = new ArrayList<Integer>();报错
}
}

1.6 可变参数

可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了

  • 格式:修饰符 返回值类型 方法名(数据类型…变量名){}
  • 范例:public static int sum(int…a){}

可变参数注意事项

  • 这里的变量其实是一个数组
  • 如果一个方法有多个参数,包含可变参数,可变参数要放在最后
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package demo_05;

public class ArgsDemo {
public static void main(String[] args) {
System.out.println(sum(50,20));
System.out.println(sum(20,58,66));
System.out.println(sum(20,58,66,45));
System.out.println(sum(20,58,66,45,60));
}
public static int sum(int... a){
int sum = 0;
for (int i:a){
sum += i;
}
return sum;
}
}

2. Map

2.1 Map集合概述和使用

Map集合概述:

  • Interface Map<K , V> K:键的类型; V:值的类型
  • 将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值
  • 举例:学生的学号和姓名
  1. 001 张三
  2. 002 李四
  3. 003 王五

创建Map集合的对象

  • 多态的方式
  • 具体的实现类HashMap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package demo_01;

import java.util.HashMap;
import java.util.Map;

public class MapDemo_01 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<String, String>();

//V put (K key, V value)将指定的值与该映射中的指定的键相关联
map.put("001","张三");
map.put("002","李四");
map.put("003","王五");
map.put("003","小陈");//键相同时后面的值会覆盖前面的值

//输出集合对象
System.out.println(map);
}
}
//运行结果
{001=张三, 002=李四, 003=小陈}

2.2 Map集合的基本功能

方法名 说明
V put(K key, V value) 添加元素
V remove(Object key) 根据键删除键值对元素
void clear() 移除所有的键值对元素
boolean containsKey(Object key) 判断集合是否包含指定的键
boolean containsValue(Object value) 判断集合是否包含指定的值
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中键值对的个数

2.3 Map集合的获取功能

方法名 说明
V get(Object key) 根据键获取值
SetkeySet() 获取所有键的集合
Collectionvalues() 获取所有值的集合
Set<Map.Entry<K,V>>entrySet() 获取所有键值对对象的集合

2.4 Map集合的遍历方式(方式1)

我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合

遍历思路:

  • 把所有的丈夫给集中起来
  • 遍历丈夫的集合,获取到每一个丈夫
  • 根据丈夫去找对应的妻子

转换为Map集合中的操作:

  • 获取所有键的集合。用keySet()方法实现
  • 遍历键的集合,获取到侮一个键。用增强for实现
  • 根据键去找值。用get(Object key)方法实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package demo_02;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo_01 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<String, String>();

//添加元素
map.put("001","hello");
map.put("002","word");
map.put("003","java");

//获取所有键的集合,用keySet()方法实现
Set<String> keyset = map.keySet();
//遍历集合,获取到每一个键,用增强for实现
for (String key:keyset){
//根据键去找值,用get(Object key)方法
String s = map.get(key);
System.out.println(key+", "+s);
}
}
}
//运行结果
001, hello
002, word
003, java

2.5 Map集合的遍历(方式2)

我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合

遍历思路:

  • 获取所有结婚证的集合
  • 遍历结婚证的集合,得到每一个结婚证
  • 根据结婚证获取丈夫和妻子

转换为Map集合中的操作:

  • 获取所有键值对对象的集合

    Set<Map.Entry<K,V>>entrySet():获取所有键值对对象的集合

  • 遍历键值对对象的集合,得到每一个键值对对象

    用增强for实现,得到每一个Map.Entry

  • 根据键值对对象获取键和值

  1. 用getKey()得到键
  2. 用getValue()得到值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package demo_02;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo_02 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<String, String>();

//添加元素
map.put("001", "hello");
map.put("002", "word");
map.put("003", "java");

//遍历集合
//1.获取所有键值对的集合
Set<Map.Entry<String, String>> entrySet = map.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for (Map.Entry<String, String> me:entrySet){
//根据键值对对象获取键和值
String key = me.getKey();
String value = me.getValue();
System.out.println(key+", "+value);
}
}
}
//运行结果
001, hello
002, word
003, java

2.6 案例:HashMap:集合存储学生对象并遍历

需求:创建一个HashMap集合,键是学号(String),值是学生对象(Student)。存储三个键值对元素,并遍历

思路:
①定义学生类
②创建HashMap集合对象
③创建学生对像
④把学生添加到集合
⑤遍历集合
方式1:键找值
方式2:键值对对象找键和值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//1.创建学生对象
package demo_03;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
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;
}
}

//2.测试类
package demo_03;

import java.util.HashMap;
import java.util.Set;

public class HashMapDemo {
public static void main(String[] args) {
//创建集合对象
HashMap<String,Student> hm = new HashMap<String, Student>();

//创建学生对象
Student s1 = new Student("张三",18);
Student s2 = new Student("李四",19);
Student s3 = new Student("王五",20);

//添加集合元素
hm.put("001",s1);
hm.put("002",s2);
hm.put("003",s3);

//遍历集合
Set<String> keySet = hm.keySet();
for (String key:keySet){
Student s = hm.get(key);
System.out.println(key+", "+s.getName()+", "+s.getAge());
}
}
}
//运行结果
001, 张三, 18
002, 李四, 19
003, 王五, 20

2.7 案例:HashMap:集合存储学生对象并遍历

需求:

  • 创建一个HashMap集合,键是学生对像(Student),值是居住地(String)。存储多个键值对元素,并遍历
  • 要求保证键的唯一性:如果学生对像的成员变量值相同,我们就认为是同一个对象

思路:
①定义学生类
②创建HashMap集合对象
③创建学生对象
④把学生添加到集合
⑤遍历集合
⑥在学生类中重写两个方法
hashCode()
equals()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
//1.创建学生类
package demo_04;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
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 boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

Student student = (Student) o;

if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}

@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
}

//2.测试类
package demo_04;

import java.util.HashMap;
import java.util.Set;

public class HashMapDemo {
public static void main(String[] args) {
//创建集合对象
HashMap<Student,String> hm = new HashMap<Student,String>();

//创建学生对象
Student s1 = new Student("张三",18);
Student s2 = new Student("李四",19);
Student s3 = new Student("王五",20);
Student s4 = new Student("王五",20);

//添加集合元素
hm.put(s1,"001");
hm.put(s2,"002");
hm.put(s3,"003");
hm.put(s4,"004");

//遍历
Set<Student> student = hm.keySet();
for (Student key:student){
String s = hm.get(key);
System.out.println(s+", "+key.getName()+", "+key.getAge());
}
}
}
//运行结果
004, 王五, 20
001, 张三, 18
002, 李四, 19

2.8 案例:ArrayList集合存储HashMap元素并遍历

需求:创建一个ArrayLists集合,存储三个元素,每一个元素都是HashMap,每一个HashMap的键和值都是String,并遍历

思路:
①创建ArrayList集合
②创建HashMap集合,并添动加键值对元素
③把HashMap作为元素添加到ArrayList集合
④遍历ArrayList集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package demo_05;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

public class ArrayListAndHashMapDemo {
public static void main(String[] args) {
//创建集合对象
ArrayList<HashMap<String, String>> array = new ArrayList<HashMap<String, String>>();

//创建HashMap集合
HashMap<String, String> hm1 = new HashMap<String, String>();
hm1.put("001", "hello");
hm1.put("002", "world");
//把HashMap作为元素添加到array集合中
array.add(hm1);

HashMap<String, String> hm2 = new HashMap<String, String>();
hm2.put("003", "java");
hm2.put("004", "python");
array.add(hm2);

HashMap<String, String> hm3 = new HashMap<String, String>();
hm3.put("005", "javaee");
hm3.put("006", "javaWeb");
array.add(hm3);

//遍历集合
for (HashMap<String, String> hm : array) {
Set<String> keyset = hm.keySet();
for (String key : keyset) {
String value = hm.get(key);
System.out.println(key + ", " + value);
}
}
}
}
//运行结果
001, hello
002, world
003, java
004, python
005, javaee
006, javaWeb

2.9 案例:HashMap:集合存储ArrayList元素并遍历

需求:

  • 创建一个HashMap集合,存储三个键值对元素,每一个键值对元素的键是String,值是ArrayList,
  • 每一个ArrayList的元素是String,并遍历

思路:
①创建HashMap:集合
②创建ArrayList集合,并添加元素
③把ArrayList作为元素添加到HashMap集合
④遍历HashMap集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package demo_05;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

public class HashMapAndArrayLIstDemo {
public static void main(String[] args) {
//创建HashMap集合对象
HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();

//创建ArrayList集合对象
ArrayList<String> array1 = new ArrayList<String>();
array1.add("hello");
array1.add("world");
//把ArrayList作为元素添加到HashMap集合中
hm.put("001", array1);

//创建ArrayList集合对象
ArrayList<String> array2 = new ArrayList<String>();
array2.add("python");
array2.add("java");
//把ArrayList作为元素添加到HashMap集合中
hm.put("002", array2);

//创建ArrayList集合对象
ArrayList<String> array3 = new ArrayList<String>();
array3.add("javaEE");
array3.add("javaWeb");
//把ArrayList作为元素添加到HashMap集合中
hm.put("003", array3);
System.out.println(hm);

//遍历集合
Set<String> keySet = hm.keySet();
for (String key : keySet) {
System.out.println(key);
ArrayList<String> value = hm.get(key);
for (String list : value) {
System.out.println("\t"+list);
}
}
}
}
//运行结果
{001=[hello, world], 002=[python, java], 003=[javaEE, javaWeb]}
001
hello
world
002
python
java
003
javaEE
javaWeb

2.10 案例:统计字符串中每个字符出现的次数

需求:键盘录入一个字符串,要求统计字符串中每个字符串出现的次数。

举例:键盘录入“aababcabcdabcde” 在控制台输出:“a(5)b(4)c(3)d(2)e(1)1

分析:
①我们可以把结果分成几个部分来看:a(5),b(4),c(3),d(2),e(1)
②每一个部分可以看成是:字符和字符对应的次数组成
③这样的数据,我们可以通过HashMap集合来存储,键是字符,值是字符出现的次数
注意:键是字符,类型应该是Character;值是字符出现的次数,类型应该是Integer

思路:
①键盘录入一个字符串
②创建HashMap集合,键是Character,值是Integer
③遍历字符串,得到每一个字符
④拿得到的每一个字符作为键到HashMap集合中去找对应的值,看其返回值
如果返回值是null:说明该字符在HashMap集合中不存在,就把该字符作为键,1作为值存储
如果返回值不是null:说明该字符在HashMap集合中存在,把该值加1,然后重新存储该字符和对应的值
⑤遍历HashMap集合,得到键和值,按照要求进行拼接
⑥输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
package demo_06;

import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
/*
①键盘录入一个字符串
②创建HashMap集合,键是Character,值是Integer
③遍历字符串,得到每一个字符
④拿得到的每一个字符作为键到HashMap集合中去找对应的值,看其返回值
如果返回值是null:说明该字符在HashMap集合中不存在,就把该字符作为键,1作为值存储
如果返回值不是null:说明该字符在HashMap集合中存在,把该值加1,然后重新存储该字符和对应的值
⑤遍历HashMap集合,得到键和值,按照要求进行拼接
⑥输出结果
*/
public class HashMapDemo {
public static void main(String[] args) {
//录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.print("请输入一个字符串:");
String line = sc.nextLine();

//创建HashMap集合对象,键是Character,值是Integer
HashMap<Character,Integer> hm = new HashMap<Character, Integer>();
//遍历字符串,得到每一个字符
for (int i = 0; i < line.length() ; i++) {
char key = line.charAt(i);

Integer value = hm.get(key);//根据键找集合中的值
if (value == null){
//如果返回值是null:说明该字符在HashMap集合中不存在,就把该字符作为键,1作为值存储
hm.put(key,1);
}else {
//如果返回值不是null:说明该字符在HashMap集合中存在,把该值加1,然后重新存储该字符和对应的值
value++;
hm.put(key,value);
}
}

//遍历HashMap集合,得到键和值,按照要求进行拼接
StringBuilder sb = new StringBuilder();

Set<Character> key1 = hm.keySet();
for (Character key:key1){
Integer value = hm.get(key);
sb.append(key).append("(").append(value).append(")");
}
String s = sb.toString();
//输出结果
System.out.println(s);
}
}
//运行结果
请输入一个字符串:aababcabcdabcde
a(5)b(4)c(3)d(2)e(1)

3.Collections

3.1 Collections概述和使用

Collections是针对集合操作的工具类

Collections类的常用方法:

方法名 说明
public static<T extends Comparable<?super T>>void sort(Listlist) 将指定的列表按升序排序
public static void reverse(List<?>list) 反转指定列表中元素的顶序
public static void shuffle(List<?>Iist) 使用默认的随机源随机排列指定的列表

3.2 案例:ArrayList存储学生对象并排序

需求:ArrayList存储学生对象,使用Collections对ArrayListi进行排序

要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序

思路:
①定义学生类
②创建ArrayLists集合对像
③创建学生对象
④把学生添加到集合
⑤使用Collections对ArrayList集合排序
⑥遍历集合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
//1.创建学生对象
package collectionsDemo;

public class Student {
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
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;
}
}

//2.测试类
package collectionsDemo;

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

public class CollectionsDemo_01 {
public static void main(String[] args) {
//创建ArrayList集合对象
ArrayList<Student> array = new ArrayList<Student>();

//创建学生对象
Student s1 = new Student("张三",18);
Student s2 = new Student("李四",19);
Student s3 = new Student("王五",20);
Student s4 = new Student("小陈",20);

//添加学生对象到集合
array.add(s1);
array.add(s2);
array.add(s3);
array.add(s4);

//使用Collections对ArrayList集合排序
Collections.sort(array, new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
int num = s1.getAge() - s2.getAge();
int num2 = num == 0?s1.getName().compareTo(s2.getName()):num;
return num2;
}
});

//遍历
for (Student s:array){
System.out.println(s.getName()+", "+s.getAge());
}
}
}
//运行结果
张三, 18
李四, 19
小陈, 20
王五, 20

3.3 模拟斗地主(案例)

4. File

4.1 File类概述和构造方法

File:它是文件和目录路径名的抽像表示

  • 文件和目录是可以通过File封装成对象的
  • 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的
方法名 说明
File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
File(String parent, String child) 从父路径名字符串和子路径名字符串创建新的File实例
File(File parent, String child) 从父抽象路径名和子路径名字符串创建新的File实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package demo_01;
/*
构造方法:
File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
File(String parent,String child):从父路径名字符串和子路径名字符串创建新的File实例
File(File parent,String child):从父抽象路径名和子路径名字符串创建新的File实例
*/
import java.io.File;

public class FileDemo01 {
public static void main(String[] args) {
//File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
File f1 = new File("D:myFile\\java.txt");
System.out.println(f1);

//File(String parent,String child):从父路径名字符串和子路径名字符串创建新的File实例
File f2 = new File("D:myFile\\","java.txt");
System.out.println(f2);

//File(File parent,String child):从父抽象路径名和子路径名字符串创建新的File实例
File f3 = new File("D:myFile\\");
File f4 = new File(f3,"java.txt");
System.out.println(f4);
}
}
//运行结果
D:myFile\java.txt
D:myFile\java.txt
D:myFile\java.txt

4.2 File类创建功能

方法名 说明
public boolean createNewFile() 当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件
public boolean mkdir() 创建由此抽象路径名命名的目录
public boolean mkdirs() 创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package demo_01;

/*
FiLe类创建功能:
public boolean createNewFile():当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件
如果文件不存在,就创建文件,并返回true
如果文件存在,就不创建文件,并返回false

public boolean mkdir():创建由此抽象路径名命名的目录
如果目录不存在,就创建目录,并返回true
如果目录存在,就不创建目录,并返回false

public boolean mkdirs():创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
*/

import java.io.File;
import java.io.IOException;

public class FileDemo02 {
public static void main(String[] args) throws IOException {
//需求1:在D:\\File目录下创建一个文件java.txt
File f1 =new File("D:\\File\\java.txt");
System.out.println(f1.createNewFile());

//需求2:在D:\\File目录下创建JavaSE目录
File f2 = new File("D:\\File\\JavaSE");
System.out.println(f2.mkdir());

//需求3:在D:\\File目录下创建一个多级目录JavaEE\\Html
File f3 = new File("D:\\File\\JavaEE\\Html");
System.out.println(f3.mkdirs());
}
}
//运行结果
true
true
true

4.3 File类判断和获取功能

方法名 说明
public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
public boolean isFile() 测试此抽象路径名表示的File是否为文件
public boolean exists() 测试此抽象路径名表示的File是否存在
public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
public String getPath() 将此抽象路径名转换为路径名字符串
public String getName() 返回由此抽象路径名表示的文件或目录的名称
public String[] list() 返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
public File[] listFiles() 返回此抽象路径名表示的目录中的文件和目录的File对像数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package demo_01;

/*
public boolean isDirectory():测试此抽象路径名表示的File是否为目录
public boolean isFile():测试此抽象路径名表示的File是否为文件
public boolean exists():测试此抽象路径名表示的File是否存在
public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
public String getPath():将此抽象路径名转换为路径名字符串
public String getName():返回由此抽象路径名表示的文件或目录的名称
public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
public File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的Fi引le对像数组
*/

import java.io.File;

public class FileDemo03 {
public static void main(String[] args) {
//创建File对象 ”D:\File\java.txt“为一个文件
File f1 = new File("D:\\File\\java.txt");

// public boolean isDirectory():测试此抽象路径名表示的File是否为目录
// public boolean isFile():测试此抽象路径名表示的File是否为文件
// public boolean exists():测试此抽象路径名表示的File是否存在
System.out.println(f1.isDirectory());
System.out.println(f1.isFile());
System.out.println(f1.exists());
System.out.println("----------");

// public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
// public String getPath():将此抽象路径名转换为路径名字符串
// public String getName():返回由此抽象路径名表示的文件或目录的名称
System.out.println(f1.getAbsolutePath());
System.out.println(f1.getPath());
System.out.println(f1.getName());
System.out.println("-----------");

// public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
// public File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的File对像数组
File f2 = new File("D:\\File");
String[] strArray = f2.list();
for (String str : strArray) {
System.out.println(str);
}
System.out.println("----------");

File[] fileArray = f2.listFiles();
for (File file:fileArray){
// System.out.println(file);
// System.out.println(file.getName());
if (file.isFile()){ //条件选择
System.out.println(file.getName());
}
}
}
}
//运行结果
false
true
true
----------
D:\File\java.txt
D:\File\java.txt
java.txt
-----------
java.txt
JavaEE
JavaSE
----------
java.txt

4.4 File删除功能

方法名 说明
public boolean delete() 删除由此抽象路径名表示的文件或目录

绝对路径和相对路径的区别:

  • 绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件。例如:E: \\itcast\\java.txt
  • 相对路径:必须使用取自其他路径名的信息进行解释。例如:myFile\\java.txt

删除目录时的注意事项:

  • 如果一个目录中有内容(目录,文件),不能直接删除。应该先删除目录中的内容,最后才能删除目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package demo_01;

import java.io.File;
import java.io.IOException;

public class FileDemo04 {
public static void main(String[] args) throws IOException {
//需求1:在当前模块下创建java.txt文件
File f1 = new File("myFile\\java.txt");
// System.out.println(f1.createNewFile());

//需求2:删除当前模块下的java.txt文件
System.out.println(f1.delete());
System.out.println("--------");

//需求3:在当前模块下创建javaEE目录
File f2 = new File("myFile\\javaEE");
// System.out.println(f2.mkdir());

//需求4:删除当前模块下的javaEE目录
System.out.println(f2.delete());

//需求5:在当前模块下创建一个目录javaSE,然后在该目录下创建java.txt文件
File f3 = new File("myFile\\javaSE");
System.out.println(f3.mkdir());
File f4 = new File("myFile\\javaSE\\java.txt");
System.out.println(f4.createNewFile());

//需求6:删除当前模块下的javaSE目录
System.out.println(f4.delete());//首先删除目录中的内容
System.out.println(f3.delete());//其次才能删除目录
}
}

4.5 递归

递归概述:以编程的角度来看,递归指的是方法定义中调用方法本身的现象

递归解决问题的思路:

把一个复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解
递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算

递归解决问题要找到两个内容:

  • 递归出口:否则会出现内存溢出
  • 递归规侧:与原问题相似的规模较小的问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package myDiGui;

public class DiGuiDemo {
public static void main(String[] args) {
//不死神兔问题,求第20个月兔子的对数
//每个月兔子对数 1,1,2,3,5,8......
int[] arr = new int[20];

arr[0] = 1;
arr[1] = 1;

for (int i = 2; i < arr.length; i++) {
arr[i] = arr[i - 1] + arr[i - 2];
}
System.out.println(arr[19]);
System.out.println(f(20));
}
/*
递归解决问题,首先就是要定义一个方法:
定义一个方法f(n):表示第n个月的兔子对数
那么,第n-1个月的兔子对数该如何表示呢?f(n-1)
同理,第n-2个月的兔子对数该如何表示呢?f(n-2)

StackOverfLowError:当堆栈溢出发生时抛出一个应用程序递归太深
*/
public static int f(int n) {
if (n == 1 || n == 2) {
return 1;
} else {
return f(n - 1) + f(n - 2);
}
}
}
//运行结果
6765
6765

4.6 递归求阶乘(案例)

需求:用递归求5的阶乘,并把结果在控制台输出

分析:
①阶乘:一个正整数的阶乘是所有小于及等于该数的正整数的积,自然数n的阶乘写作n!
5!=5*4*3*2*1
②递归出口:1!=1
③递归规则:n!=n*(n-1) 5!=5*4!

思路:
①定义一个方法,用于递归求阶乘,参数为一个int类型的变量
②在方法内部判断该变量的值是否是1
是:返回1
不是:返回n*(n-1)!
③调用方法
④输出结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package myDiGui;

public class JeiChengDemo {
public static void main(String[] args) {
int fn = f(5);
System.out.println(fn);
}

//定义一个方法,用于递归求阶乘,参数为一个int类型的变量
public static int f(int n) {
//在方法内部判断该变量的值是否是1
if (n == 1) {
//是:返回1
return 1;
} else {
//不是:返回n*(n-1)!
return n * f(n - 1);
}
}
}
//运行结果
120

4.7 遍历目录(案例)

需求:给定一个路径(D:\\File),请通过递归完成遍历该目录下的所有内容,并把所有文件的绝对路径输出在控制台

思路:
①根据给定的路径创建一个File对象
②定义一个方法,用于获取给定目录下的所有内容,参数为第1步创建的File对像
③获取给定的File目录下所有的文件或者目录的File数组
④遍历该File数组,得到每一个File对像
⑤判断该File对象是否是目录
是:递归调用
不是:获取绝对路径输出在控制台
⑥调用方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package myDiGui;

/* 根据给定的路径创建一个File对象
定义一个方法,用于获取给定目录下的所有内容,参数为第1步创建的File对像
获取给定的File目录下所有的文件或者目录的File数组
遍历该File数组,得到每一个File对像
判断该File对象是否是目录
是:递归调用
不是:获取绝对路径输出在控制台
调用方法
*/
import java.io.File;

public class DirDemo {
public static void main(String[] args) {
//根据给定的路径创建一个File对象
File srcFile = new File("D:\\File");
getAllFilePath(srcFile);
}
public static void getAllFilePath(File srcFile){
//获取给定的File目录下所有的文件或者目录的File数组
File[] fileArray = srcFile.listFiles();
//遍历该File数组,得到每一个File对像
if (fileArray != null){
for (File file:fileArray){
//判断该File对象是否是目录
if (file.isDirectory()){
getAllFilePath(file);
}else {
System.out.println(file.getAbsolutePath());
}
}
}
}
}
//运行结果
D:\File\java.txt
D:\File\JavaEE\Html\python.txt