集合进阶
1. Collection
1.1集合知识回顾
集合类的特点:提供一种存储空间可控的存储模型,存储的数据容量可以随时发生改变
1.2集合类体系结构
ArrayList
List(可重复)【
LinkedList
Collection(单列集合)例:张三,李四,王五【
HashSet
Set(不可重复【
集合【 TreeSet
HashMap
Map(双列集合)例:Itcast1:张三,Itcast2:李四,Itcast3:王五【
其他...
1.3 Collection 集合概述和使用
Collection集合概述
-
是单列集合的顶层接口,他表示一组对象,这些对象也称为Collection的元素
-
JDK不提供此接口的任何直接实现,它提供更具体的子接口 (如Set和List)实现
创建Collection集合的对象
-
多态的方式
-
具体的实现类ArrayList()
package CollectionDemo01;
import java.util.ArrayList;
import java.util.Collection;
/**
* 创建Collection集合的对象
*
* - 多态的方式
* - 具体的实现类ArrayList()
*/
public class CollectionDemo01 {
public static void main(String[] args) {
//创建Collection集合的对象
//多态的方式
Collection<String> c = new
<String>();
//添加元素,boolean add (E e)
c.add("Hello");
c.add("World");
c.add("Java");
//输出集合对象
System.out.println(c);
}
}
[Hello, World, Java]
1.4 Collection 集合常用方法
| 方法名 | 说明 |
|---|---|
| boolean add(E e) | 添加元素 |
| boolean remove(Object o) | 从集合中移除指定元素 |
| void clear() | 清空集合中的元素 |
| boolean contains(Object o) | 判断集合中是否存在指定的元素 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 集合的长度,也就是集合中元素的个数 |
package CollectionDemo01;
import java.util.ArrayList;
import java.util.Collection;
/**
* Collection 集合常用方法
* boolean add(E e)添加元素
* boolean remove(Object o)从集合中移除指定元素
* void clear()清空集合中的元素
* boolean contains(Object o)判断集合中是否存在指定的元素
* boolean isEmpty()判断集合是否为空
* int size()集合的长度,也就是集合中元素的个数
*
* Alt+7 打开一个窗口,能够看到类的所有信息
*/
public class CollectionDemo02 {
public static void main(String[] args) {
Collection<String> c=new ArrayList<String>();
//boolean add(E e)添加元素
System.out.println(c.add("hello"));
System.out.println(c.add("world"));
System.out.println(c.add("java"));
c.add("hello");
c.add("world");
c.add("java");
//boolean remove(Object o)从集合中移除指定元素
System.out.println(c.remove("world"));
System.out.println(c.remove("javaee"));
//void clear()清空集合中的元素
c.clear();
//boolean contains(Object o)判断集合中是否存在指定的元素
System.out.println(c.contains("world"));
System.out.println(c.contains("javaee"));
//boolean isEmpty()判断集合是否为空
System.out.println(c.isEmpty());
//int size()集合的长度,也就是集合中元素的个数
System.out.println(c.size());
//输出集合对象
System.out.println(c);
}
}
1.5 Collection 集合的遍历
迭代器就是一个内部类,是内部类最常见用途
Iterator: 迭代器,集合的专用遍历方式
-
Iterator<E>Iterator():返回此集合中元素的迭代器;通过集合的iterator()方法得到
-
迭代器是通过集合lterator()方法的到的,所以我们说它是依赖于集合而存在的
Iterator中的常用方法
-
E next(); 返回迭代中的下一个元素
-
boolean hasNext(); 如果迭代具有更多元素,则返回true
package CollectionDemo01;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* Iterator: 迭代器,集合的专用遍历方式
* Iterator<E>Iterator():返回此集合中元素的迭代器;通过集合的iterator()方法得到
* 迭代器是通过集合Iterator()方法的到的,所以我们说它是依赖于集合而存在的
*
*Iterator中的常用方法
* E next(); 返回迭代中的下一个元素
* boolean hasNext(); 如果迭代具有更多元素,则返回true
*/
public class CollectionDemo03 {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
//添加元素
c.add("hello");
c.add("world");
c.add("java");
//Iterator<E>Iterator():返回此集合中元素的迭代器;通过集合的iterator()方法得到
Iterator<String> it = c.iterator();
/*
public Iterator<E> iterator() {
return new Itr();
}
private class Itr implements Iterator<E> {
...
}
*/
//E next(); 返回迭代中的下一个元素
/**
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());
System.out.println(it.next());//NoSuchElementException:表示被请求的元素不存在
*/
//boolean hasNext(); 如果迭代具有更多元素,则返回true
/** if(it.hasNext()){
System.out.println(it.next());
}
if(it.hasNext()){
System.out.println(it.next());
}
if(it.hasNext()){
System.out.println(it.next());
}
if(it.hasNext()){
System.out.println(it.next());
}
*/
//用while循环改进判断
while(it.hasNext()){
// System.out.println(it.next());
String s = it.next();
System.out.println(s);
}
}
}
hello
world
java
1.6集合的使用步骤
public static void main(String[] args) {
//创建集合
Collection<String> c = new ArrayList<String>();
//添加元素
c.add("hello");
c.add("world");
c.add("java");
//迭代器获取判断集合中的元素,有元素则输出该元素,没有元素则进不了判断,程序结束
Iterator<String> it = c.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
}
public static void main(String[] args) {
//步骤1:创建集合对象
Collection<String> c = new ArrayList<String>();
//步骤2:添加元素
//步骤2.1:添加元素到集合
String s ="itcast";
//步骤2.2:添加元素到集合
c.add(s);
//合并:添加元素到集合
c.add("itcast");
//步骤3:遍历集合
//步骤3.1:通过集合对象获取迭代器对象
Iterator<String> it = c.iterator();
//步骤3.2:通过迭代器对象的hasNext()方法判断是否还有元素
while(it.hasNext()){
//步骤3.3:通过迭代器对象的next()方法获取下一个元素
String s = it.next();
System.out.println(s);
}
}
Collection集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历集合
思路:
-
定义学生对象
-
创建Collection集合对象
-
创建学生对象
-
把学生添加到集合
-
遍历集合(迭代器方式)
package CollectionDemo01;
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;
}
package CollectionDemo01;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/*
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历集合
思路:
1. 定义学生对象
2. 创建Collection集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 遍历集合(迭代器方式)
*/
public class CollectionDemo04 {
public static void main(String[] args) {
//创建Collection集合对象
Collection<Student> c = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student("德邦",24);
Student s2 = new Student("德玛",25);
Student s3 = new Student("嘉文",24);
//把学生添加到集合
c.add(s1);
c.add(s2);
c.add(s3);
//遍历集合(迭代器方式)
Iterator<Student> it = c.iterator();
//判断是否有元素
while(it.hasNext()){
//获取元素
Student s = it.next();
//在Student 类中重写 to String ,后面可以直接打印输出s
System.out.println(s);
}
}
}
Student 姓名:德邦 , 年龄:24
Student 姓名:德玛 , 年龄:25
Student 姓名:嘉文 , 年龄:24
2. List(元素可重复)
List集合概述
-
有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置,用户可以通过整数索引访问元素,并搜索列表中的元素
-
与Set集合不同,列表通常允许重复的元素
List 集合的特点
-
有序:存储和取出的元素顺序一致
-
可重复:存储的元素可重复
package ListDemo01;
/*
List 集合的特点
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可重复
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Demo01 {
public static void main(String[] args) {
//创建集合对象
List<String> list =new ArrayList<String>();
//添加元素
list.add("hello");
list.add("world");
list.add("java");
list.add("world");
//输出集合对象
// System.out.println(list);
//迭代器的方式遍历
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s=it.next();
System.out.println(s);
}
}
}
//体现的特点:有序和可重复
hello
world
java
world
2.2 list集合特有方法
| 方 法 | 说明 |
|---|---|
| void add(index,E element) | 在此集合中的指定位置插入指定指定元素 |
| E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
| E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
| E get(int index) | 返回指定索引处的元素 |
元素排序都是从0开始的
package ListDemo01;
/*
list集合特有方法
方 法 说明
void add(index,E element) 在此集合中的指定位置插入指定指定元素
E remove(int index) 删除指定索引处的元素,返回被删除的元素
E set(int index,E element) 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素
*/
import java.util.ArrayList;
import java.util.List;
public class Demo02 {
public static void main(String[] args) {
//创建集合对象
List<String> s = new ArrayList<String>();
//添加元素
s.add("hello");
s.add("world");
s.add("java");
//void add(index,E element) | 在此集合中的指定位置插入指定指定元素
//在第1个位置处添加元素
s.add(1,"javaee");
//IndexOutOfBoundsException越界检查(异常)
s.add(11,"javaee");
//E remove(int index) | 删除指定索引处的元素,返回被删除的元素
//删除第1个位置的元素
System.out.println(s.remove(1));
//IndexOutOfBoundsException越界检查(异常)
System.out.println(s.remove(11));
//E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素
System.out.println(s.set(1,"javaee"));
//IndexOutOfBoundsException越界检查(异常)
System.out.println(s.set(11,"javaee"));
//E get(int index) | 返回指定索引处的元素
System.out.println(s.get(1));
//IndexOutOfBoundsException越界检查(异常)
System.out.println(s.get(11));
//输出集合对象
System.out.println(s);
//遍历集合
System.out.println(s.get(0));
System.out.println(s.get(1));
System.out.println(s.get(2));
//用for循环改进遍历
for (int i=0;i<s.size();i++){
String si=s.get(i);
System.out.println(si);
}
}
}
案例:List集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
思路:
-
定义学生类
-
创建List集合对象
-
创建学生对象
-
把学生添加到集合
-
遍历集合(迭代器方式,for循环方式)
package ListDemo02;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/*
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
思路:
1. 定义学生类
2. 创建List集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 遍历集合(迭代器方式,for循环方式)
*/
public class ListDemo {
public static void main(String[] args) {
//创建List集合对象
List<Student> list = new ArrayList<Student>();
//创建学生对象
Student s1=new Student("林青霞",32);
Student s2=new Student("张曼玉",35);
Student s3=new Student("王祖贤",38);
//把学生添加到集合
//多态的形式
list.add(s1);
list.add(s2);
list.add(s3);
//迭代器方式遍历
Iterator<Student> it = list.iterator();
while (it.hasNext()){
Student s =it.next();
System.out.println(s);
}
System.out.println("---------------------------------");
//for循环方式遍历
for (int i=0;i<list.size();i++){
Student s = list.get(i);
System.out.println(s);
}
}
}
Student姓名:林青霞, 年龄:32
Student姓名:张曼玉, 年龄:35
Student姓名:王祖贤, 年龄:38
---------------------------------
Student姓名:林青霞, 年龄:32
Student姓名:张曼玉, 年龄:35
Student姓名:王祖贤, 年龄:38
2.3并发修改异常
并发修改异常
-
ConcurrentModificationException
产生原因
-
迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致
解决方案
-
用for循环遍历,然后用集合对象做对应的操作即可
2.4 Listlterator
Listlterator:列表迭代器
-
通过List集合的Listlterator()方法得到,所以说它是List集合特有的迭代器
-
用于允许程序员沿任意方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
Listlterator 中的常用方法
| 方法 | 说明 |
|---|---|
| E next() | 返回迭代器中下一个元素 |
| boolean hasNext() | 如果迭代具有更多元素,则返回true |
| E previous() | 返回列表中的上一个元素 |
| boolean hasPrevious() | 如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true |
| void add(E e) | 将指定的元素插入列表 |
package Listlterator;
/*
Listlterator:列表迭代器
通过List集合的Listlterator()方法得到,所以说它是List集合特有的迭代器
用于允许程序员沿任意方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
Listlterator 中的常用方法
方法 说明
E next() 返回迭代器中下一个元素
boolean hasNext() 如果迭代具有更多元素,则返回true
E previous() 返回列表中的上一个元素
boolean hasPrevious() 如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true
void add(E e) 将指定的元素插入列表
*/
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class Demo {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<String>();
//添加元素
list.add("hello");
list.add("world");
list.add("java");
//通过List集合的Listlterator()方法得到
//正向遍历
// ListIterator<String> lit = list.listIterator();
// while(lit.hasNext()){
// String s=lit.next();
// System.out.println(s);
// }
// System.out.println("----------------");
//
// //逆向遍历
// while (lit.hasPrevious()){
// String s =lit.previous();
// System.out.println(s);
// }
//过去列表迭代器
ListIterator<String> lit = list.listIterator();
while (lit.hasNext()){
String s = lit.next();
if (s.equals("world")){
lit.add("javaee");
}
}
System.out.println(list);
}
}
2.5增强for循环
增强for:简化数组和Collection集合的遍历
-
实现lterable接口的类允许其对象成为增强型for语句的目标
-
它是JDK5之后出现的,其内部原理是一个lterator迭代器
增强for的格式
-
格式:
for(元素数据类型变量名:数据或者Collection集合){
//在此处使用变量集合即可,该变量就是元素
}
-
范例:
int[] arr=[1,2,3,4,5];
for(int i: arr){
System.out.println(i);
}
package Listlterator;
import java.util.ArrayList;
import java.util.List;
/*
2.5增强for循环
增强for:简化数组和Collection集合的遍历
- 实现lterable接口的类允许其对象成为增强型for语句的目标
- 它是JDK5之后出现的,其内部原理是一个lterator迭代器
增强for的格式
- 格式:
for(元素数据类型变量名:数据或者Collection集合){
//在此处使用变量集合即可,该变量就是元素
}
- 范例:
int[] arr=[1,2,3,4,5];
for(int i: arr){
System.out.println(i);
}
*/
public class Dome01 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
for (int i:arr){
System.out.println(i);
}
System.out.println("--------");
String[] strArray = {"hello","world","java"};
for (String s:strArray){
System.out.println(s);
}
System.out.println("-------");
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("java");
for (String ss:list){
System.out.println(ss);
}
System.out.println("--------");
//for内部原理是一个Iterator迭代器
// for (String s:list){
// if (s.equals("world")){
// list.add("javaee");//ConcurrentModificationException
// }
// }
}
}
1
2
3
4
5
--------
hello
world
java
-------
hello
world
java
-------- -
案例:List集合存储学生对象用三种方式遍历
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
思路:
-
定义学生类
-
创建List集合对象
-
创建学生对象
-
把学生添加到集合
-
遍历集合
-
迭代器:集合特有的遍历方式
-
普通for:带有索引的遍历方式
-
增强for:最方便的遍历方式
-
package Listlterator01;
//学生类
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 String toString() {
return "学生" +
" 姓名:" + name +
", 年龄:" + age ;
}
}
package Listlterator01;
/*
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
思路:
1. 定义学生类
2. 创建List集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 遍历集合
- 迭代器:集合特有的遍历方式
- 普通for:带有索引的遍历方式
- 增强for:最方便的遍历方式
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListDemo {
public static void main(String[] args) {
List<Student> list=new ArrayList<>();
//创建学生对象
Student s1 = new Student("林青霞",30);
Student s2 = new Student("张玉曼",35);
Student s3 = new Student("王祖贤",33);
//把学生添加到集合
list.add(s1);
list.add(s2);
list.add(s3);
//遍历集合
Iterator<Student> it = list.iterator();
while (it.hasNext()){
Student ss = it.next();
System.out.println(ss);
}
System.out.println("---------------");
//普通for:带有索引的遍历方式
for (int i=0;i<list.size();i++){
Student ss1 = list.get(i);
System.out.println(ss1);
}
System.out.println("---------------");
//增强for:最方便的遍历方式
for (Student ss2:list){
System.out.println(ss2);
}
}
}
学生 姓名:林青霞, 年龄:30
学生 姓名:张玉曼, 年龄:35
学生 姓名:王祖贤, 年龄:33
---------------
学生 姓名:林青霞, 年龄:30
学生 姓名:张玉曼, 年龄:35
学生 姓名:王祖贤, 年龄:33
---------------
学生 姓名:林青霞, 年龄:30
学生 姓名:张玉曼, 年龄:35
学生 姓名:王祖贤, 年龄:33
2.6 数据结构
数据结构是计算机存储,组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合通常情况下,精心选择的数据结构可以带来更高的运行或存储效率
2.7常见数据结构之栈
数据进入栈模型的过程称为:压/进栈
数据离开栈模型的过程称为:弹/出栈
栈是一种数据先进后出的模型
2.8常见数据结构之队列
数据从后端进入队列模型的过程称为:入队列
数据从前端离开队列模型的过程称为:出队列
队列是一种数据先进先出的模型
2.9常见数据结构之数组
查询数据通过索引定位,查询任意数据耗时相同,查询效率高
删除数据时,要将原始数据删除,同时后面每个数据前移,删除效率低
添加数据时,添加位置后的每个数据后移,再添加元素,添加效率极低
总结:数组是一种查询快,增删慢的模型
2.10常见数据结构之链表
优点:链表是一种增删快的模型(对比数组)
缺点:链表是一种查询慢的模型(对比数组)
查询数据D是否存在,必须从头(head)开始查询
查询第3个数据,必须从头(head)开始查询
2.11 List集合子类特点
List集合常用子类:ArrayList,LinkedList
-
ArrayList:底层数据结构是数组,查询快,增删慢
-
LinkedList:底层数据结构是链表,查询慢,增删快
练习:
分别使用ArrayList和LinkedList完成存储字符串并遍历
package itheima_01;
/*
List集合常用子类:ArrayList,LinkedList
- ArrayList:底层数据结构是数组,查询快,增删慢
- LinkedList:底层数据结构是链表,查询慢,增删快
练习:
分别使用ArrayList和LinkedList完成存储字符串并遍历
*/
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
public class ListDemo {
public static void main(String[] args) {
//创建ArrayList集合对象
ArrayList<String> array =new ArrayList<String>();
array.add("hello");
array.add("world");
array.add("java");
//增强for遍历
for (String ss1:array){
System.out.println(ss1);
}
System.out.println("-----------");
//迭代器遍历
Iterator<String> it = array.iterator();
while (it.hasNext()){
String ss2 = it.next();
System.out.println(ss2);
}
System.out.println("-----------");
//普通for遍历
for (int i = 0; i<array.size(); i++){
String ss3 = array.get(i);
System.out.println(ss3);
}
System.out.println("-----------");
//创建LinkedList集合对象
LinkedList<String> linked = new LinkedList<String>();
linked.add("hello");
linked.add("world");
linked.add("java");
//增强for遍历
for (String s1:linked){
System.out.println(s1);
}
System.out.println("-----------");
//迭代器遍历
Iterator<String> is = linked.iterator();
while (is.hasNext()){
String sss = is.next();
System.out.println(sss);
}
System.out.println("-----------");
//普通for遍历
for (int i=0;i<linked.size();i++){
String sss1 = linked.get(i);
System.out.println(sss1);
}
}
}
hello
world
java
-----------
hello
world
java
-----------
hello
world
java
-----------
hello
world
java
-----------
hello
world
java
-----------
hello
world
java
案例:ArrayList集合储存学生对象用三种方式遍历
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
思路:
-
定义学生类
-
创建ArrayList集合对象
-
创建学生对象
-
把学生添加到集合
-
遍历该集合
-
迭代器:集合特有的遍历方式
-
普通for:带有索引的遍历方式
-
增强for:最便利的遍历方式
-
package itheima_02;
//定义学生类
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 String toString() {
return "Student " +
"姓名:" + name +
" , 年龄:" + age
;
}
}
package itheima_02;
/*
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
思路:
1. 定义学生类
2. 创建ArrayList集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 遍历该集合
*/
import java.util.ArrayList;
import java.util.Iterator;
public class Dome01 {
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);
//把学生添加到集合
array.add(s1);
array.add(s2);
array.add(s3);
//迭代器遍历
Iterator<Student> it = array.iterator();
while (it.hasNext()){
Student ss1 = it.next();
System.out.println(ss1);
}
System.out.println("----------");
//普通for遍历
for (int i=0;i<array.size();i++){
Student ss2 = array.get(i);
System.out.println(ss2);
}
System.out.println("----------");
//增强for遍历
for (Student ss3:array){
System.out.println(ss3);
}
System.out.println("----------");
}
}
Student 姓名:张三 , 年龄:18
Student 姓名:李四 , 年龄:19
Student 姓名:王五 , 年龄:20
----------
Student 姓名:张三 , 年龄:18
Student 姓名:李四 , 年龄:19
Student 姓名:王五 , 年龄:20
----------
Student 姓名:张三 , 年龄:18
Student 姓名:李四 , 年龄:19
Student 姓名:王五 , 年龄:20
----------
package itheima_02;
/*
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
思路:
1. 定义学生类
2. 创建LinkedList集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 遍历该集合
*/
import java.util.Iterator;
import java.util.LinkedList;
public class Dome02 {
public static void main(String[] args) {
////创建LankedList集合对象
LinkedList<Student> linked = new LinkedList<Student>();
//创建学生对象
Student s1 = new Student("周星驰",57);
Student s2 = new Student("刘德华",58);
Student s3 = new Student("成龙",64);
//把学生添加到集合
linked.add(s1);
linked.add(s2);
linked.add(s3);
//迭代器遍历
Iterator<Student> it = linked.iterator();
while (it.hasNext()){
Student ss1 = it.next();
System.out.println(ss1);
}
System.out.println("----------");
//普通for遍历
for (int i=0;i<linked.size();i++){
Student ss2 = linked.get(i);
System.out.println(ss2);
}
System.out.println("----------");
//增强for遍历
for (Student ss3:linked){
System.out.println(ss3);
}
}
}
Student 姓名:周星驰 , 年龄:57
Student 姓名:刘德华 , 年龄:58
Student 姓名:成龙 , 年龄:64
----------
Student 姓名:周星驰 , 年龄:57
Student 姓名:刘德华 , 年龄:58
Student 姓名:成龙 , 年龄:64
----------
Student 姓名:周星驰 , 年龄:57
Student 姓名:刘德华 , 年龄:58
Student 姓名:成龙 , 年龄:64
2.12 LinkedList集合的特有功能
| 方法名 | 说明 |
|---|---|
| public voidaddFirst(E e) | 在该列表开头插入指定的元素 |
| public voidaddLast(E e) | 将指定的元素追加到此列表的末尾 |
| public E getFirst() | 返回此列表中的第一个元素(类似复制) |
| public E getLast() | 返回此列表中最后一个元素(类似复制) |
| public E remove First() | 从此列表中删除并返回第一个元素(类似剪切) |
| public E remove Last() | 从此列表中删除并返回最后一个元素(类似剪切) |
package itheima_03;
/*
LinkedList集合的特有功能
| 方法名 | 说明 |
| -------------------------- | -------------------------------- |
| public void addFirst(E e) | 在该列表开头插入指定的元素 |
| public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
| public E getFirst() | 返回此列表中的第一个元素 |
| public E getLast() | 返回此列表中最后一个元素 |
| public E removeFirst() | 从此列表中删除并返回第一个元素 |
| public E removeLast() | 从此列表中删除并返回最后一个元素 |
*/
import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
//创建集合对象
LinkedList<String> linkedList=new LinkedList<String>();
linkedList.add("hello");
linkedList.add("world");
linkedList.add("java");
// public void addFirst(E e) | 在该列表开头插入指定的元素
// |public void addLast(E e) | 将指定的元素追加到此列表的末尾
// linkedList.addFirst("javase");
// linkedList.addLast("javaee");
// System.out.println(linkedList);
输出结果:
[javase, hello, world, java, javaee]
// public E getFirst() | 返回此列表中的第一个元素
// public E getLast() | 返回此列表中最后一个元素
// System.out.println(linkedList.getFirst());
// System.out.println(linkedList.getLast());
// System.out.println(linkedList);
输出结果:
hello
java
[hello, world, java]
// public E removeFirst() | 从此列表中删除并返回第一个元素
// public E removeLast() | 从此列表中删除并返回最后一个元素
// System.out.println(linkedList.removeFirst());
// System.out.println(linkedList.removeLast());
// System.out.println(linkedList);
输出结果:
hello
java
[world]
}
}
3 Set(元素不可重复)
Set集合特点
-
不包含重复元素的集合
-
没有带索引的方法,所以不能使用普通for循环遍历
package itheima_04;
/*
Set集合特点
- 不包含重复元素的集合
- 没有带索引的方法,所以不能使用不同for循环遍历
HashSet:对集合的迭代顺序不作任何保证(随机)
*/
import java.util.HashSet;
import java.util.Set;
public class SetDemo {
public static void main(String[] args) {
//创建集合对象
Set<String> set = new HashSet<String>();
//添加元素
set.add("hello");
set.add("world");
set.add("java");
//不包含重复元素的集合
set.add("world");
//遍历
for (String s:set){
System.out.println(s);
}
}
}
输出结果:
world
java
hello
特点:
-
HashSet:对集合的迭代顺序不作任何保证(随机性)
-
不包含重复元素的集合
3.2 哈希值
哈希值: 是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
-
public int hashCode(); 返回对象的哈希码值
对象的哈希值特点:
-
同一个对象多次调用hashCode()方法返回的哈希值是相同的
-
默认情况下,不同对象的哈希值是不同的,而重写hashCode()方法,可以实现让不同对象的哈希值相同
package itheima_05;
/*
哈希值:
是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
public int hashCode(); 返回对象的哈希码值
*/
public class HashDemo {
public static void main(String[] args) {
//创建学生对象
Student s1 = new Student("林青霞",30);
//同一个对象多次使用hashCode()方法返回的哈希值是相同的
System.out.println(s1.hashCode());//2003749087
System.out.println(s1.hashCode());//2003749087
System.out.println("----------------");
Student s2 = new Student("林青霞",30);
//默认情况下,不同对象的哈希值是不相同的
//通过方法重写,可以实现不同对象的哈希值是相同的
System.out.println(s2.hashCode());//1324119927
System.out.println("----------------");
System.out.println("hello".hashCode());//99162322
System.out.println("world".hashCode());//113318802
System.out.println("java".hashCode());//3254818
System.out.println("world".hashCode());//113318802
System.out.println("----------------");
System.out.println("重地".hashCode());//1179395
System.out.println("通话".hashCode());//1179395
}
}
3.3 HashSet集合概述和特点
HashSet集合特点:
-
底层数据结构是哈希表
-
对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
-
没有带索引的方法,所以不能使用普通for循环遍历
-
由于是Set集合,所以是不包含重复元素的集合
HashSet集合练习
-
存储字符串并遍历
package hashDemo_01;
/*
HashSet集合特点:
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
*/
import java.util.HashSet;
public class Demo01 {
public static void main(String[] args) {
//创建集合对象
HashSet<String> hashSet=new HashSet<>();
//添加元素
hashSet.add("hello");
hashSet.add("world");
hashSet.add("java");
//再次添加world
hashSet.add("world");
//遍历
for (String s:hashSet){
System.out.println(s);
}
}
}
输出结果:
world
java
hello
3.4 HashSet集合保证元素唯一性源码分析
HashSet集合添加一个元素的过程:
HashSet集合保证元素唯一的源码分析
//创建集合对象
HashSet<String> hashSet=new HashSet<>();
//添加元素
hashSet.add("hello");
hashSet.add("world");
hashSet.add("java");
-------------------------------------------------------------
public boolean add(E e) {
return map.put(e, PRESENT)==null;
}
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
//hash值和元素hashCode()方法相关
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
//如果哈希表未初始化,就对其进行初始化
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
//根据根据对象的哈希值计算对象的存储位置,如果该位置没有元素,就存储元素
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
/*
存入的元素和以前的元素比较哈希值
如果哈希值不同,会继续向下执行,把元素添加到集合
如果哈希值相同,会调用对象的equals()方法比较
如果返回false,会继续向下执行,把元素添加到集合
如果返回true,说明元素重复,不存储
*/
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
if (e != null) { // existing mapping for key
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
return oldValue;
}
}
++modCount;
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}
HashSet集合存储元素:
-
要保证元素唯一性,需要重写 hashCode() 和 equals()
3.5 常见数据结构之哈希表
哈希表
-
JDK8之前,低层采用 数组+链表 实现,可以说一个元素为链表的数组
-
JDK8以后,在长度比较长的时候,底层实现了优化
存储方式:
-
哈希值相同,先比较对象是否相等,对象相等再使用 equals() 方法比较内容
案例:HashSet集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对象
思路:
-
定义学生类
-
创建Hash Set集合对象
-
创建学生对象
-
把学生添加到集合
-
遍历集合(增强for)
-
在学生类中重写两个方法
package itheima_06;
//学生类
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 String toString() {
return "Student " +
"姓名:" + name +
" , 年龄:" + age
;
}
//重写HashSet方法
@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;
}
}
package itheima_06;
/*
需求:创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对象
思路:
1. 定义学生类
2. 创建HashSet集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 遍历集合(增强for)
*/
import java.util.HashSet;
public class Hash {
public static void main(String[] args) {
//创建HashSet集合对象
HashSet<Student> student = new HashSet<Student>();
//创建学生对象
Student s1 = new Student("张三",18);
Student s2 = new Student("李四",19);
Student s3 = new Student("王五",20);
Student s4 = new Student("王五",20);
//把学生添加到集合
student.add(s1);
student.add(s2);
student.add(s3);
student.add(s4);
//遍历集合(增强for)
for (Student s:student){
System.out.println(s);
}
}
}
Student 姓名:王五 , 年龄:20
Student 姓名:张三 , 年龄:18
Student 姓名:李四 , 年龄:19
Hash Set两个方法重写:
-
因为new出来的内容虽然一样但地址值不一样,所以需要重写方法
3.6 LinkedHashSet集合概述和特点
LinkedHashSet集合特点
-
哈希表和链表实现的Set接口,具有可预测的迭代次序
-
由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
-
由哈希表保证元素唯一,也就是说没有重复的元素
LinkedHashSet集合联系
-
存储字符串并遍历
package itheima.itheima_07;
/*
LinkedHashSet集合特点
- **哈希表和链表实现的Set接口,具有可预测的迭代次序**
- **由链表保证元素有序,也就是说元素的存储和取出顺序是一致的**
- **由哈希表保证元素唯一,也就是说没有重复的元素**
*/
import java.util.LinkedHashSet;
public class LinkedHashSetDome {
public static void main(String[] args) {
//创建集合对象
LinkedHashSet<String> linked= new LinkedHashSet<String>();
//添加元素
linked.add("hello");
linked.add("world");
linked.add("java");
//由哈希表保证元素唯一,也就是说没有重复的元素,所以不会输出第二个world
linked.add("world");
//便利集合
for (String s:linked){
System.out.println(s);
}
}
}
hello
world
java
3.7 TreeSet集合概述的特点
TreeSet集合特点
-
元素有序,这里的有序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
-
Treet(): 根据元素的自然排序进行排序
-
Treet(Comparator comparator): 根据指定的比较器进行排序
-
-
没有带索引的方法,所以不能普通for循环遍历
-
由于是Set集合,所以不包含重复元素的集合
TreeSet集合练习
-
存储整数并遍历
package itheima.itheima_08;
/*
TreeSet集合特点
元素有序,这里的有序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
Treet(): 根据元素的自然排序进行排序
Treet(Comparator comparator): 根据指定的比较器进行排序
没有带索引的方法,所以不能普通for循环遍历
由于是Set集合,所以不包含重复元素的集合
*/
import java.util.TreeSet;
public class TreeSetDome {
public static void main(String[] args) {
//创建集合对象
//因为要用引用类型,所以这里不能直接用int,要用int的包装类Integer
//所有基本类型存储的时候用对应的包装类类型
TreeSet<Integer> treeSet = new TreeSet<Integer>();
//添加元素
treeSet.add(10);
treeSet.add(50);
treeSet.add(40);
treeSet.add(20);
treeSet.add(30);
//不包含重复元素
treeSet.add(30);
//遍历集合
for(Integer i:treeSet){
System.out.println(i);
}
}
}
10
20
30
40
50
3.8 自然排序Comparable的使用(方法一)
-
此接口对实现它的每个类的对象强加一个总排序。 这种排序被称为类的自然顺序 ,类的
compareTo方法被称为其自然比较方法 -
存储学生对象并遍历,创建TreeSet集合使用无参构造方法
-
要求:按照年龄从小到大排序,年龄相同时,按照名字的字母顺序排序
package itheima.itheima_09;
//学生类
public class Student implements Comparable<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 String toString() {
return "Student " +
"姓名:" + name +
" , 年龄:" + age
;
}
@Override
public int compareTo(Student s) {
// 如果返回值是0,说明元素是重复的,所以它就不会存储我们添加的元素
// return 0;//不存储
// 如果返回值是1,后面的元素会一直默认比前一个元素大,所以他就按照自然排序的顺序进行输出
// return 1;//升序
// 如果返回值是-1,后面的元素会一直默认比前一个元素小,所以他就按照自然排序反顺序进行输出
// return -1;//降序
//主要条件
//按照年龄从小到大排序
//升序
int num = this.age - s.age;
//按照年龄从大到小排序
//降序
// int num = s.age - this.age;
//次要条件
//年龄相同时,按照名字的字母顺序排序
//年龄相同时,比较名字的首字母因为String字符串中有自然排序,所以可以直接调用compareTo(String)
//可以保证元素的唯一性
int num2 = num==0?this.name.compareTo(s.name):num;
return num2;
}
}
package itheima.itheima_09;
/*
存储学生对象并遍历,创建TreeSet集合使用无参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照名字的字母顺序排序
*/
import java.util.TreeSet;
public class TreeSetDome {
public static void main(String[] args) {
//创建集合对象
TreeSet<Student> ts=new TreeSet<Student>();
//创建学生对象
Student s1=new Student("xishi",19);
Student s2=new Student("wangzhaojun",20);
Student s3=new Student("diaochan",18);
Student s4=new Student("yangyuhuan",23);
Student s5=new Student("linqingxia",23);
Student s6=new Student("linqingxia",23);
//把学生添加到集合
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
//遍历
for (Student s:ts){
System.out.println(s);
}
}
}
Student 姓名:diaochan , 年龄:18
Student 姓名:xishi , 年龄:19
Student 姓名:wangzhaojun , 年龄:20
Student 姓名:linqingxia , 年龄:23
Student 姓名:yangyuhuan , 年龄:23
结论:
-
用TreeSet集合储存自定义对象,无参构造方法使用的是自然排序对元素进行排序的
-
自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(To)方法
-
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
3.9 比较器排序Comparator的使用(方法二)
-
存储学生对象并遍历,创建TreeSet集合使用带参构造方法
-
要求,按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序进行排序
package itheima.itheima_010;
//学生类
public class Student {
private String name;
private int age;
public Student(){};
public Student(String name,int age){
this.name=name;
this.age=age;
}
public void setName(String name){
this.name=name;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age=age;
}
public int getAge(){
return age;
}
@Override
public String toString() {
return "Student " +
"姓名:" + name +
" , 年龄:" + age
;
}
}
package itheima.itheima_010;
/*
存储学生对象并遍历,创建TreeSet集合使用带参构造方法
要求,按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序进行排序
*/
import java.util.Comparator;
import java.util.TreeSet;
public class ComparatorDome {
public static void main(String[] args) {
//创建集合对象
TreeSet<Student> stu = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//this.age - s.age
//s1,s2
//局部内部类Comparator作为参数
int num = s1.getAge()-s2.getAge();
int num2 = num == 0 ?s1.getName().compareTo(s2.getName()) :num;
return num2;
}
});
//创建学生
Student s1=new Student("diaocan",18);
Student s2=new Student("dwangzhaojun",19);
Student s3=new Student("canwenji",18);
Student s4=new Student("daqiao",23);
//由于Set不包含重复元素的集合,所以只会有一个元素被输出
Student s5=new Student("lingqingxia",23);
Student s6=new Student("lingqingxia",23);
//添加元素
stu.add(s1);
stu.add(s2);
stu.add(s3);
stu.add(s4);
stu.add(s5);
stu.add(s6);
//遍历
for (Student s:stu){
System.out.println(s);
}
}
}
结论
-
用TreeSet存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
-
比较器排序。就是让集合构造方法接受Conparator的1实现类对象,重写compare(To1,To2)方法
-
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
案例:成绩排序
需求:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合
要求:按照总分从高到底出现
思路:
-
定义学生类
-
创建TreeSet集合对象,通过比较器排序进行排序
-
创建学生对象
-
把学生对象添加集合
-
遍历
方法一(推荐比较器排序)
package itheima.itheima_011;
//学生类
public class Student {
private String name;
private int Sc;//语文成绩
private int Ma;//数学成绩
public Student(){}
public Student(String name, int sc, int ma) {
this.name = name;
Sc = sc;
Ma = ma;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getSc() {
return Sc;
}
public void setSc(int sc) {
Sc = sc;
}
public int getMa() {
return Ma;
}
public void setMa(int ma) {
Ma = ma;
}
public int getSum(){
return this.Sc+this.Ma;
}
@Override
public String toString() {
return "Student " +
"姓名:" + name +
" , 语文成绩:" + Sc +
" , 数学成绩:" + Ma +
" , 总成绩:" +getSum()
;
}
}
package itheima.itheima_011;
/*
需求:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合
要求:按照总分从高到底出现
思路:
1. 定义学生类
2. 创建TreeSet集合对象,通过比较器排序进行排序
3. 创建学生对象
4. 把学生对象添加集合
5. 遍历
*/
import java.util.Comparator;
import java.util.TreeSet;
public class ComparatorDome {
public static void main(String[] args) {
//创建集合对象,通过比较器排序进行排序
TreeSet<Student> stu = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// 如果元素过多就不方便了(不建议)
// int num = (s2.getSc()+s2.getMa())-(s1.getSc()+s1.getMa());
//主要条件
int num =s2.getSum()- s1.getSum();
//次要条件
int num2=num==0?s2.getSc()-s1.getSc():num;
//次要条件
int num3=num2==0?s2.getName().compareTo(s1.getName()):num2;
return num3;
}
});
//添加学生
Student s1 = new Student("林曼玉",59,77);
Student s2 = new Student("张曼玉",61,88);
Student s3 = new Student("王祖贤",99,59);
Student s4 = new Student("柳岩",74,33);
Student s5 = new Student("风清扬",44,90);
Student s6 = new Student("左冷禅",60,98);
Student s7 = new Student("赵云",60,98);
//把学生添加到集合
stu.add(s1);
stu.add(s2);
stu.add(s3);
stu.add(s4);
stu.add(s5);
stu.add(s6);
stu.add(s7);
//遍历
for (Student s:stu){
System.out.println(s);
}
}
}
方法二(自然排序)
package itheima.itheima_012;
//学生类
public class Student implements Comparable<Student>{
private String name;
private int chinese;
private int math;
public Student(){}
public Student(String name, int chinese, int math) {
this.name = name;
this.chinese = chinese;
this.math = math;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getChinese() {
return chinese;
}
public void setChinese(int chinese) {
this.chinese = chinese;
}
public int getMath() {
return math;
}
public void setMath(int math) {
this.math = math;
}
public int getSum(){
return this.chinese+this.math;
}
@Override
public String toString() {
return "Student " +
"姓名:" + name +
" , 语文成绩:" + chinese +
" , 数学成绩:" + math +
" , 总成绩:" +getSum()
;
}
@Override
public int compareTo(Student s) {
//主要条件
int num = s.getSum()-this.getSum();
//次要条件
int num2=num==0?s.getChinese()-this.getChinese():num;
//次要条件
int num3=num2==0?s.getName().compareTo(this.getName()):num2;
return num3;
}
}
package itheima.itheima_012;
import java.util.TreeSet;
/*
需求:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合
要求:按照总分从高到底出现
思路:
1. 定义学生类
2. 创建TreeSet集合对象,通过比较器排序进行排序
3. 创建学生对象
4. 把学生对象添加集合
5. 遍历
*/
public class ComparatorDome {
public static void main(String[] args) {
//创建集合对象
TreeSet<Student> stu=new TreeSet<Student>();
//添加学生
Student s1 = new Student("林曼玉",98,100);
Student s2 = new Student("张曼玉",61,88);
Student s3 = new Student("王祖贤",99,59);
Student s4 = new Student("柳岩",74,33);
Student s5 = new Student("风清扬",44,90);
Student s6 = new Student("左冷禅",60,98);
Student s7 = new Student("赵云",60,98);
//把学生添加到集合
stu.add(s1);
stu.add(s2);
stu.add(s3);
stu.add(s4);
stu.add(s5);
stu.add(s6);
stu.add(s7);
//遍历
for (Student s:stu){
System.out.println(s);
}
}
}
Student 姓名:林曼玉 , 语文成绩:98 , 数学成绩:100 , 总成绩:198
Student 姓名:王祖贤 , 语文成绩:99 , 数学成绩:59 , 总成绩:158
Student 姓名:赵云 , 语文成绩:60 , 数学成绩:98 , 总成绩:158
Student 姓名:左冷禅 , 语文成绩:60 , 数学成绩:98 , 总成绩:158
Student 姓名:张曼玉 , 语文成绩:61 , 数学成绩:88 , 总成绩:149
Student 姓名:风清扬 , 语文成绩:44 , 数学成绩:90 , 总成绩:134
Student 姓名:柳岩 , 语文成绩:74 , 数学成绩:33 , 总成绩:107
案例:不重复的随机数
Random:该类的实例用于生成伪随机数流
需求:编写一个程序,获取10个1~20之间的随机数,要求随机数不能重复,并在控制台输出
思路:
-
创建Set集合对象
-
创建随机数对象
-
判断随机数的长度是不是小于10(Random)
-
是:产生一个随机数,添加到集合
-
回到3继续
-
-
遍历集合
package itheima.itheima_013;
/*
需求:编写一个程序,获取10个~20个之间的随机数,要求随机数不能重复,并在控制台输出
思路:
1. 创建Set集合对象
2. 创建随机数对象
3. 判断随机数的长度是不是小于10
- 是:产生一个随机数,添加到集合
- 回到3继续
4. 遍历集合
*/
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
public class SetDome {
public static void main(String[] args) {
//添加集合对象
//HashSet随机排序
//TreeSet自然排序
// Set<Integer> set=new HashSet<Integer>();
Set<Integer> set=new TreeSet<Integer>();
//创建随机数对象
Random r=new Random();
//判断集合的长度是不是小于10,也就是设定10个数
while(set.size()<10){
//产生一个1~20的随机数,添加到集合
//如果只填20这里就是0~19,+1就是1~20,不加不能去除0
int number = r.nextInt(20)+1;
set.add(number);
}
//遍历集合
for (Integer i:set){
System.out.println(i);
}
}
}
3
4
6
8
10
12
15
17
19
20
4.泛型
泛型:是JDK5中引入得特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法得类型
它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数
一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参,那么参数化类型怎么理解呢?
顾名思义:就是将类型由原来的具体类型参数化,然后再使用/调用时传入具体的类型
这种参数类型可以在类,方法和接口中,分别被称为泛型类,泛型方法,泛型接口
泛型定义格式:
-
<类型>:指定一种类型的格式,这里的类型可以看成是形参
-
<类型1,类型2,类型3......>:指定多种类型的格式,多种类型之间用逗号隔开,这里的类型可以看成是形参
-
将来具体调用的时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型
package itheima.itheima_014;
/*
需求: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("world");
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);
//Object强制向下转型为String类型
// String s = (String) it.next();//ClassCastException类型转换异常
String s = it.next();//这里就不需要强制类型装换
System.out.println(s);
}
}
}
hello
world
java
泛型的好处:
-
把运行时期的问题提前到了编译期
-
避免了强制类型转换
4.2 泛型类
泛型类的定义格式:
-
格式:修饰符 class 类名<类型>{ }
-
范例:public class Generic<T>{ }
-
此处T可以随意写为任意标识,常见的如T,E,K,V等形式的参数常用于表示泛型
-
-
总结:泛型类就是模板类,可以在测试类中,可以定义任意引用数据类型
package itheima.itheima_015;
//泛型类(模板类)
public class Generi<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
package itheima.itheima_015;
//学生类
public class Student {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package itheima.itheima_015;
//老师类
public class Teacher {
private Integer age;
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
package itheima.itheima_015;
//测试类
public class Test {
public static void main(String[] args) {
Student s = new Student();
s.setName("林青霞");
System.out.println(s.getName());
Teacher t = new Teacher();
t.setAge(28);
System.out.println(t.getAge());
System.out.println("--------------------");
Generi<String> g1 = new Generi<String>();
g1.setT("张曼玉");
System.out.println(g1.getT());
Generi<Integer> g2= new Generi<Integer>();
g2.setT(30);
System.out.println(g2.getT());
Generi<Boolean> g3 = new Generi<Boolean>();
g3.setT(true);
System.out.println(g3.getT());
}
}
林青霞
28
--------------------
张曼玉
30
true
4.3泛型方法
泛型方法的定义格式:
-
格式:修饰符<类型>返回值类型方法名(类型 变量名){ }
-
范例:public <T> void show(T t){ }
-
总结:泛型方法可以输出任意类型数据
package itheima.itheima_016;
/*
//常规步骤
public class Generic {
public void show(String s){
System.out.println(s);
}
public void show(Integer i){
System.out.println(i);
}
public void show(Boolean b){
System.out.println(b);
}
}
*/
//泛型类改进
//public class Generic<T>{
// public void show(T t){
// System.out.println(t);
// }
//}
//泛型方法改进
public class Generic{
public <T> void show(T t){
System.out.println(t);
}
}
package itheima.itheima_016;
/*
测试类
*/
public class GenericDemo {
public static void main(String[] args) {
// Generic g = new Generic();
// g.show("林青霞");
// g.show(28);
// g.show(true);
// Generic<String> g1 = new Generic<String>();
// g1.show("张学友");
//
// Generic<Integer> g2 = new Generic<Integer>();
// g2.show(30);
//
// Generic<Boolean> g3 = new Generic<Boolean>();
// g3.show(true);
Generic g = new Generic();
g.show("郭富城");
g.show(32);
g.show(true);
g.show(66.66);
}
}
郭富城
32
true
66.66
4.4泛型接口
泛型接口的定义格式:
-
格式:修饰符interface 接口名<类型>{ }
-
范例:public interface Generic<T>{ }
package itheima.itheima_017;
/*
接口类
*/
public interface Generic <T>{
void show(T t);
}
package itheima.itheima_017;
/*
继承类
*/
public class GenericImpl<T> implements Generic<T> {
@Override
public void show(T t) {
System.out.println(t);
}
}
package itheima.itheima_017;
/*
测试类
*/
public class GenericDemo {
public static void main(String[] args) {
GenericImpl<String> g1 = new GenericImpl<String>();
g1.show("林青霞");
GenericImpl<Integer> g2 = new GenericImpl<Integer>();
g2.show(28);
}
}
林青霞
28
4.5类型通配符
为了表示各种泛型List的父类,可以使用类型通配符
-
类型通配符: <?>
-
List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
-
这种带通配符的List仅表示他是各种泛型List的父类,并不能把元素添加到其中
如果我们不希望List<?>是任意泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
-
类型通配符上限:<?extends 类型>
-
List<? extends Number>: 它表示的类型是Number或者其子类型
除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限
-
类型通配符下限:<?super 类型>
-
List<? super Number>:它表示的类型是Number或者其父类型
package itheima.itheima_018;
/*
- 类型通配符: <?>
- List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
- 这种带通配符的List仅表示他是各种泛型List的父类,并不能把元素添加到其中
如果我们不希望List<?>是任意泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
- 类型通配符上限:<?extends 类型>
- List<? extends Number>: 它表示的类型是:Number或者其子类型
除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限
- 类型通配符下限:<?super 类型>
- List<? super Number>:它表示的类型是Number或者其父类型
*/
import java.util.ArrayList;
import java.util.List;
public class GenericDemo {
public static void main(String[] args) {
//List<?>
List<?> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<Number>();
List<?> list3 = new ArrayList<Integer>();
System.out.println("---------");
//List<? extends Number>
//Object是Number的父类,所以最高上限不能高于Number
// List<? extends Number> list4 = new ArrayList<Object>();
List<? extends Number> list5 = new ArrayList<Number>();
List<? extends Number> list6 = new ArrayList<Integer>();
System.out.println("---------");
//List<? super Number>
List<? super Number> list7 = new ArrayList<Object>();
List<? super Number> list8 = new ArrayList<Number>();
//Integer是Number的子类,所以最低下限不能低于Number
// List<? super Number> list9 = new ArrayList<Integer>();
}
}
4.6 可变参数
可变参数又称参数的个数可变,用作方法的形参出现,那么方法参数的个数就是可变的了
-
格式:修饰符 返回值类型 方法名 (数据类型...变量名){ }
-
范例:public static int sum(int...a){ }
可变参数注意事项
-
这里的变量其实是一个数组
-
如果一个方法有多个参数,包含可变参数,可变参数要放到最后面
package itheima.itheima_019;
/*
测试类
*/
public class ArgsDemo01 {
public static void main(String[] args) {
System.out.println(sum(10,20));
System.out.println(sum(10,20,30));
System.out.println(sum(10,20,30,40));
System.out.println(sum(10,20,30,40,50));
System.out.println(sum(10,20,30,40,50,60));
System.out.println(sum(10,20,30,40,50,60,70));
}
//有多种参数又包含可变参数,把可变参数放最后
// public static int sum(int b,int...a){
// return 0;
// }
public static int sum(int...a){
int sum = 0;
for (int i:a){
sum +=i;
}
return sum;
}
// 数组参数过多就不好使用
// public static int sum(int a,int b){
// return a + b;
// }
//
// public static int sum(int a,int b,int c){
// return a + b + c;
// }
//
// public static int sum(int a,int b,int c,int d){
// return a + b + c + d;
// }
}
30
60
100
150
210
280
4.7 可变参数的使用
Arrays工具类中有一个静态方法
-
public static <T> List<T> asList(T...a): 返回由指定数组支持的固定大小的列表
-
返回的集合不能做增删操作,可以做修改操作
List接口中有一个静态方法:
-
public static <E> List <E> of(E...elements):返回包含任意数量元素的不可变列表
-
返回的集合不能做增删该操作
Set接口中有一个静态方法
-
public static <E> Set<E> of(E...elements):返回一个包含任意数量元素的不可变集合
-
在给元素的时候,不能给重复的元素
-
返回的集合不能做增删操作,没有修改的方法
package Demoxx.demo_01;
/*
Arrays工具类中有一个静态方法
- public static <T> List<T> asList(T...a): 返回由指定数组支持的固定大小的列表
List接口中有一个静态方法:
- public static <E> List <E> of(E...elements):返回包含任意数量元素的不可变列表
Set接口中有一个静态方法
- public static <E> Set<E> of(E...elements):返回一个包含任意数量元素的不可变集合
*/
import java.util.Arrays;
import java.util.List;
import java.util.Set;
public class ArgsDemo01 {
public static void main(String[] args) {
//public static <T> List<T> asList(T...a): 返回由指定数组支持的固定大小的列表
// List<String> list = Arrays.asList("hello", "world", "java");
// 添加和删除改变集合的大小,所以不支持
// 添加元素 list.add("javaee");UnsupportedOperationException
// 删除元素 list.remove("world");UnsupportedOperationException
// 修改元素不会改变集合大小,所以支持
list.set(2,"javaee");
System.out.println(list);
//public static <E> List <E> of(E...elements):返回包含任意数量元素的不可变列表
List<String> list=List.of("hello","world","java","world");
// 添加元素 list.add("javaee");UnsupportedOperationException
// 删除元素 list.remove("world");UnsupportedOperationException
// 修改元素 list.set(3,"worlds");UnsupportedOperationException
System.out.println(list);
//public static <E> Set<E> of(E...elements):返回一个包含任意数量元素的不可变集合
// Set<String> set = Set.of("hello", "world", "java","world");//IllegalArgumentException
Set<String> set = Set.of("hello", "world", "java");//IllegalArgumentException
set.add("javaee");//UnsupportedOperationException
set.remove("world");//UnsupportedOperationException
System.out.println(set);
}
}
异常:
-
UnsupportedOperationException:抛出以指示不支持所请求的操作。
-
IllegalArgumentException:抛出以指示方法已被传递非法或不适当的参数。
5.MAP
5.1 Map集合概述和使用
-
Interface Map<K,V> K:键的类型;V:值得类型
-
将键映射到值得对象:不能包含重复的键:每个键可以映射到最多一个值
-
举例:学生的学号和姓名 - itheima001 林青霞 - itheima002 张曼玉 - itheima003 王祖贤
创建Map集合的对象
-
多态的方式
-
具体的实现类HashMap
package Demoxx.demo_02;
import java.util.HashMap;
import java.util.Map;
/*
Map集合概述和使用
- Interface Map<K,V> K:键的类型;V:值得类型
- 将键映射到值得对象:不能包含重复的键:每个键可以映射到最多一个值
- 举例:学生的学号和姓名
- itheima001 林青霞
- itheima002 张曼玉
- itheima003 王祖贤
创建Map集合的对象
- 多态的方式
- 具体的实现类HashMap
*/
public class MapDemo01 {
public static void main(String[] args) {
//添加集合对象
Map<String,String> map = new HashMap<String,String>();
//V put(K key, V value) 将指定的值与此映射中的指定键相关联(可选操作)。
map.put("itheima001","林青霞");
map.put("itheima002","张曼玉");
map.put("itheima003","王祖贤");
//当键(Key)重复时,后面的值会吧前面的值替换掉
map.put("itheima003","柳岩");
//输出集合对象
System.out.println(map);
}
}
{itheima003=柳岩, itheima001=林青霞, itheima002=张曼玉}
5.2 Map集合的基本功能
| 方法名 | 说明 |
|---|---|
| V put(K key,V value) | 添加元素 |
| V remove(Object key) | 根据键删除键值对元素 |
| void clear() | 移除所有键值对元素 |
| boolean contains Key(Object value) | 判断集合是否包含指定的键 |
| boolean contains Value(Object value) | 判断集合是否包含指定的值 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 集合的长度,也就是集合中键值对的个数 |
package Demoxx.demo_02;
/*
##### Map集合的基本功能
| 方法名 | 说明 |
| :----------------------------------: | :----------------------------------: |
| V put(K key,V value) | 添加元素 |
| V remove(Object key) | 根据键删除键值对元素 |
| void clear() | 移除所有键值对元素 |
| boolean contains Key(Object value) | 判断集合是否包含指定的键 |
| boolean contains Value(Object value) | 判断集合是否包含指定的值 |
| boolean isEmpty() | 判断集合是否为空 |
| int size() | 集合的长度,也就是集合中键值对的个数 |
*/
import java.util.HashMap;
import java.util.Map;
public class MapDemo02 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
//V put(K key,V value) 添加元素
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
//V remove(Object key) 根据键删除键值对元素
System.out.println(map.remove("杨过"));
System.out.println(map);
//void clear() 移除所有键值对元素
map.clear();
System.out.println(map);
//boolean containsKey(Object value) 判断集合是否包含指定的键
//boolean contains Value(Object value) | 判断集合是否包含指定的值
System.out.println(map.containsKey("张无忌"));
System.out.println(map.containsValue("赵敏"));
//boolean isEmpty() 判断集合是否为空
System.out.println(map.isEmpty());
//int size() 集合的长度,也就是集合中键值对的个数
System.out.println(map.size());
}
}
5.3 Map集合的获取功能
| 方法名 | 说明 |
|---|---|
| V get(Object key) | 根据键获取值 |
| Set<K> keySet() | 获取所有键的集合 |
| Collection<V> values() | 获取所有值的集合 |
| Set<Map,Entry<K,V>>entrySet() | 获取所有键值对对象的集合 |
package Demoxx.demo_03;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Mapdemo03 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
//V get(Object key)根据键获取值
System.out.println(map.get("张无忌"));
System.out.println(map.get("张三丰"));
System.out.println("-----------------");
//Set<K> keySet()获取所有键的集合
Set<String> keySet = map.keySet();
for (String s:keySet){
System.out.println(s);
}
System.out.println("-----------------");
//Collection<V> values()获取所有值的集合
Collection<String> values = map.values();
for (String value:values){
System.out.println(value);
}
}
}
赵敏
null
-----------------
杨过
郭靖
张无忌
-----------------
小龙女
黄蓉
赵敏
5.4 Map集合的遍历(方式一)
我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合
遍历思路
-
把所有的丈夫给集中起来
-
遍历丈夫的集合,获取到每个丈夫
-
根据丈夫去找对应的妻子
转换为Map集合中的操作:
-
获取所有键的集合,用keySet()方法实现
-
遍历键的集合,获取到每个键,用增强for实现
-
根据键去找值,用get(Object key)方法实现
package Demoxx.demo_04;
/*
转换为Map集合中的操作:
- 获取所有键的集合,用keySet()方法实现
- 遍历键的集合,获取到每个键,用增强for实现
- 根据键去找值,用get(Object key)方法实现
*/
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo04 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
//获取所有键的集合,用keySet()方法实现
Set<String> keySet = map.keySet();
//遍历键的集合,获取到每个键,用增强for实现
for (String key:keySet){
//根据键去找值,用get(Object key)方法实现
String value = map.get(key);
System.out.println(key+","+value);
}
}
}
杨过,小龙女
郭靖,黄蓉
张无忌,赵敏
5.5 Map集合的遍历(方式二)
我们刚才存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合遍历思路
-
获取所有结婚证的集合
-
遍历结婚证的集合,得到每一个结婚证
-
根据结婚证获取丈夫和妻子
转换为Map集合中的操作:
-
获取所有键值对对象的集合
Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
-
遍历键值对对象的集合,得到每一个键值对对象
用增强for实现,得到么一个Map.Entry
-
根据键值对对象获取键和值
-
用getKey()得到键
-
用getValue()得到值
-
package Demoxx.demo_05;
/*
转换为Map集合中的操作:
- 获取所有键值对对象的集合
Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
- 遍历键值对对象的集合,得到每一个键值对对象
用增强for实现,得到每一个Map.Entry
- 根据键值对对象获取键和值
- 用getKey()得到键
- 用getValue()得到值
*/
import java.util.HashMap;
import java.util.Set;
public class Map {
public static void main(String[] args) {
//创建集合对象
java.util.Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("张无忌","赵敏");
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
//获取所有键值对对象的集合
Set<java.util.Map.Entry<String, String>> entrySet = map.entrySet();
//用增强for实现,得到每一个Map.Entry
for (java.util.Map.Entry<String, String> me:entrySet){
//根据键值对对象获取键和值
String key = me.getKey();
String value = me.getValue();
System.out.println(key+","+value);
}
}
}
杨过,小龙女
郭靖,黄蓉
张无忌,赵敏
案例:HashMap集合存储学生对象并遍历
需求:创建一个HashMap集合,键是学号(String),值是学生对象(Student),存储三个键值对元素,并遍历
思路;
-
定义学生类
-
创建HashMap集合对象
-
创建学生对象
-
把学生添加到集合
-
遍历集合
-
方式一:键伐值
-
方法二:键值对对象找键和值
-
package Demoxx.demo_06;
/*
需求:创建一个HashMap集合,键是学号(String),值是学生对象(Student),存储三个键值对元素,并遍历
思路;
1. 定义学生类
2. 创建HashMap集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 遍历集合
- 方式一:键伐值
- 方法二:键值对对象找键和值
*/
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapDemo {
public static void main(String[] args) {
//创建HashMap集合对象
HashMap<String,Student> st = new HashMap<String,Student>();
//创建学生对象
Student s1 = new Student("林青霞",35);
Student s2 = new Student("张曼玉",29);
Student s3 = new Student("王祖贤",28);
//把学生添加到集合
st.put("itheima001",s1);
st.put("itheima002",s2);
st.put("itheima003",s3);
//遍历集合(方式一:键伐值)
Set<String> keySet = st.keySet();
for (String key:keySet){
Student student = st.get(key);
System.out.println(key+","+student);
}
System.out.println("----------------");
//遍历集合(方法二:键值对对象找键和值)
//HashMap的遍历方式
Set<Map.Entry<String, Student>> entrySet = st.entrySet();
for (Map.Entry<String, Student> ee:entrySet){
String key1 = ee.getKey();
Student value2 = ee.getValue();
System.out.println(key1+","+value2);
}
}
}
itheima003,姓名:王祖贤 , 年龄:28
itheima001,姓名:林青霞 , 年龄:35
itheima002,姓名:张曼玉 , 年龄:29
----------------
itheima003,姓名:王祖贤 , 年龄:28
itheima001,姓名:林青霞 , 年龄:35
itheima002,姓名:张曼玉 , 年龄:29
案例:HashMap集合存储学生对象并遍历
需求:创建一个HashMap集合,键是学生对象(Student),值是居住地,存储多个键值对元素,并遍历
要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
思路:
-
定义学生类
-
创建HashMap集合对象
-
创建学生对象
-
把学生添加到集合
-
遍历集合
-
在学生类中重写两个方法
-
hashCode
-
equals()
-
package Demoxx.demo_07;
//学生类
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 String toString() {
return "姓名:" + name +
" , 年龄:" + 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;
}
}
package Demoxx.demo_07;
/*
需求:创建一个HashMap集合,键是学生对象(Student),值是居住地,存储多个键值对元素,并遍历
要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象
思路:
1. 定义学生类
2. 创建HashMap集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 遍历集合
6. 在学生类中重写两个方法
- hashCode
- equals()
*/
import java.util.HashMap;
import java.util.Set;
public class HashMapDemo {
public static void main(String[] args) {
//创建HashMap集合对象
HashMap<Student,String> st = new HashMap<Student,String>();
//创建学生对象
Student s1 = new Student("林青霞",35);
Student s2 = new Student("张曼玉",29);
Student s3 = new Student("王祖贤",28);
Student s4 = new Student("王祖贤",28);
//把学生添加到集合
st.put(s1,"西安");
st.put(s2,"武汉");
st.put(s3,"南京");
st.put(s4,"北京");
//遍历集合
//HashMap的遍历方式
Set<Student> students = st.keySet();
for (Student key:students){
String value = st.get(key);
System.out.println(key+","+value);
}
}
}
姓名:林青霞 , 年龄:35,西安
姓名:王祖贤 , 年龄:28,北京
姓名:张曼玉 , 年龄:29,武汉
案例:ArrayList集合存储HashMap元素并遍历
需求:创建一个ArrayList集合,存储三个元素,每个元素都是HashMap,每一个HashMap的键和值都是String ,并遍历
思路:
-
创建ArrayList集合
-
创建HashMap集合,并添加键值对元素
-
把HashMap作为元素添加到ArrayList集合
-
遍历ArrayList集合
package Demoxx.demo_08;
/*
需求:创建一个ArrayList集合,存储三个元素,每个元素都是HashMap,每一个HashMap的键和值都是String ,并遍历
思路:
1. 创建ArrayList集合
2. 创建HashMap集合,并添加键值对元素
3. 把HashMap作为元素添加到ArrayList集合
4. 遍历ArrayList集合
*/
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class ArrayListIncludeHashMapDemo {
public static void main(String[] args) {
//创建ArrayList集合
ArrayList<HashMap<String,String>> array = new ArrayList<HashMap<String,String>>();
//创建HashMap集合,并添加键值对元素
HashMap<String,String> hash1 = new HashMap<String,String>();
hash1.put("孙策","大乔");
hash1.put("周瑜","小乔");
HashMap<String,String> hash2 = new HashMap<String,String>();
hash2.put("郭靖","黄蓉");
hash2.put("杨过","小龙女");
HashMap<String,String> hash3 = new HashMap<String,String>();
hash3.put("令狐冲","任盈盈");
hash3.put("林平之","岳灵珊");
//把HashMap作为元素添加到ArrayList集合
array.add(hash1);
array.add(hash2);
array.add(hash3);
//遍历ArrayList集合
for (HashMap<String,String> s:array){
//HashMap的遍历方式
Set<String> keySet = s.keySet();
for (String key :keySet){
String value = s.get(key);
System.out.println(key+","+value);
}
}
}
}
孙策,大乔
周瑜,小乔
杨过,小龙女
郭靖,黄蓉
令狐冲,任盈盈
林平之,岳灵珊
案例:HashMap集合存储ArrayList元素并遍历
需求:创建一个HashMap集合,存储三个键值对元素,每一个键值对元素的键是String,值是ArrayList,
每一个ArrayList的元素是String,并遍历
思路:
-
创建HahMap集合
-
创建ArrayList集合,并添加元素
-
把ArrayList作为元素添加到HashMap集合
-
遍历HashMap集合
package Demoxx.demo_09;
/*
需求:创建一个HashMap集合,存储三个键值对元素,每一个键值对元素的键是String,值是ArrayList,
每一个ArrayList的元素是String,并遍历
思路:
1. 创建HahMap集合
2. 创建ArrayList集合,并添加元素
3. 把ArrayList作为元素添加到HashMap集合
4. 遍历HashMap集合
*/
import LX.CC.A;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class HashMapArrayListIncludeDemo {
public static void main(String[] args) {
//创建HahMap集合
//元素的键是String,值是ArrayList
HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();
//创建ArrayList集合,并添加元素
//把ArrayList作为元素添加到HashMap集合
ArrayList<String> array1 = new ArrayList<String>();
array1.add("诸葛亮");
array1.add("赵云");
hm.put("三国演义",array1);
ArrayList<String> array2 = new ArrayList<String>();
array1.add("唐僧");
array1.add("孙悟空");
hm.put("西游记",array2);
ArrayList<String> array3 = new ArrayList<String>();
array1.add("武松");
array1.add("鲁智深");
hm.put("水浒传",array3);
//遍历HashMap集合
Set<String> keySet = hm.keySet();
for (String key:keySet){
System.out.println(key);
ArrayList<String> value = hm.get(key);
for (String s:value){
System.out.println("\t" + s);
}
}
}
}
水浒传
三国演义
诸葛亮
赵云
唐僧
孙悟空
武松
鲁智深
西游记
HashSet保证唯一性,不保证顺序
案例:统计字符串中每个字符出现的次数
需求:键盘录入一个字符串要求统计字符串中每个字符串出现的次数。
举例:键盘录入 ”aababcabcdabcde“ 在控制台输出: "a(5)b(4)c(3)d(2)e(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,得到键和值,按照要求进行拼接
-
输出拼接结果
package Demoxx.demo_010;
/*
需求:键盘录入一个字符串要求统计字符串中每个字符串出现的次数。
举例:键盘录入 ”aababcabcdabcde“ 在控制台输出: "a(5)b(4)c(3)d(2)e(1)"
思路:
1. 键盘录入一个字符串
2. 创建HashMap集合,键是Character ,值是Integer
3. 遍历字符串,得到每一个字符
4. 拿到每一个字符作为键到HashMap集合中去找对应的值,看其返回值
- 如果返回值是null:说明该字符在HashMap中不存在,就把该字符作为键,1作为值储存
- 如果返回值不是null:说明该字符在HashMap中存在,就把该值加1,然后重新储存该字符
5. 遍历HashMap,得到键和值,按照要求进行拼接
6. 输出结果
*/
import java.util.HashMap;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;
public class HashMapDome {
public static void main(String[] args) {
//键盘录入一个字符串
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
//创建HashMap集合,键是Character ,值是Integer
TreeMap<Character,Integer> hm= new TreeMap<Character,Integer>();
//遍历字符串,得到每一个字符
for (int i=0;i<line.length();i++){
char key = line.charAt(i);
//拿到每一个字符作为键到HashMap集合中去找对应的值,看其返回值
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> keySet = hm.keySet();
for (Character key:keySet){
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)
6. Collections
6.1Collections概述和使用
Collections类的概述
-
是针对集合操作的工具类
Collections类的常用方法
-
public static<T extends Comparable<? super T >> void sort(List<T> list):将指定的列表按升序排列
-
public static void reverse(List<?>list):反转指定列表中元素的顺序
-
public static void shuffle(List<?> list):使用默认的随机源随机排列指定的排列
-
Collections.sort(list);
-
Collections.reverse(list);
-
Collections.shuffle(list);
package Demoxx.demo_011;
/*
Collections类的概述
- 是针对集合操作的工具类
Collections类的常用方法
- public static<T extends Comparable<? super T >> void sort(List<T> list):将指定的列表按升序排列
- public static void reverse(List<?>list):反转指定列表中元素的顺序
- public static void shuffle(List<?> list):使用默认的随机源随机排列指定的排列
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsDemo01 {
public static void main(String[] args) {
//创建集合对象
List<Integer> list = new ArrayList<Integer>();
//添加元素
list.add(40);
list.add(30);
list.add(50);
list.add(10);
list.add(20);
//public static<T extends Comparable<? super T >> void sort(List<T> list):将指定的列表按升序排列
Collections.sort(list);
//public static void reverse(List<?>list):反转指定列表中元素的顺序
Collections.reverse(list);
//public static void shuffle(List<?> list):使用默认的随机源随机排列指定的排列
Collections.shuffle(list);
//遍历集合
for (Integer i:list){
System.out.println(i);
}
}
}
案例:ArrayList储存学生对象并排列
需求:ArrayList存储学生对象,使用Collections对ArrayList进行排列
要求:按照年龄从小到大排序,年龄相等时,按照姓名的字母顺序排序
思路:
-
定义学生类
-
创建ArrayList集合对象
-
创建学生对象
-
把学生添加到集合
-
使用Collections对ArrayList集合排序
-
遍历集合
package Demoxx.demo_012;
/*
需求:ArrayList存储学生对象,使用Collections对ArrayList进行排列
要求:按照年龄从小到大排序,年龄相等时,按照姓名的字母顺序排序
思路:
1. 定义学生类
2. 创建ArrayList集合对象
3. 创建学生对象
4. 把学生添加到集合
5. 使用Collections对ArrayList集合排序
6. 遍历集合
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class CollectionsDemo {
public static void main(String[] args) {
//创建ArrayList集合对象
ArrayList<Student> array = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student("lingqingxia",21);
Student s2 = new Student("zhangmanyu",23);
Student s3 = new Student("wangzhuxian",24);
Student s4 = new Student("liuyan",23);
//把学生添加到集合
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);
}
}
}
姓名:lingqingxia , 年龄:21
姓名:liuyan , 年龄:23
姓名:zhangmanyu , 年龄:23
姓名:wangzhuxian , 年龄:24
案例:模拟斗地主
需求:通过程序实现斗地主过程中的洗牌,发牌和看牌
思路:
-
创建一个牌盒,也就是定义一个集合对象,用ArrayList集合实现
-
往牌盒里装牌
-
洗牌,也就是把牌打散,用Collections的shuffle()方法实现1
-
发牌,也就是遍历集合,给三个玩家发牌
-
看牌,也就是三个玩家分别遍历自己的牌
package Demoxx.demo_013;
/*
需求:通过程序实现斗地主过程中的洗牌,发牌和看牌
思路:
1. 创建一个牌盒,也就是定义一个集合对象,用ArrayList集合实现
2. 往牌盒里装牌
3. 洗牌,也就是把牌打散,用Collections的shuffle()方法实现1
4. 发牌,也就是遍历集合,给三个玩家发牌
5. 看牌,也就是三个玩家分别遍历自己的牌
*/
import java.util.ArrayList;
import java.util.Collections;
public class PokerDemo {
public static void main(String[] args) {
// 创建一个牌盒,也就是定义一个集合对象,用ArrayList集合实现
ArrayList<String> array = new ArrayList<String>();
//往牌盒里装牌
/*
♦2,♦3,♦4,♦5...♦K,♦A
♣2,♣3,♣4,♣5...♣K,♣A
♠2,♠3,♠4,♠5...♠K,♠A
♥2,♥3,♥4,♥5...♥K,♥A
大王,小王
*/
//定义花色数租
String[] colors = {"♦","♣","♠","♥"};
//定义点数租
String[] numbers = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
//外循环"♦","♣","♠","♥"
for (String color:colors){
//内循环"2","3"..."Q","K","A"
for (String number:numbers){
//进行合体拼接
array.add(color+number);
}
}
//存入大小王
array.add("小王");
array.add("大王");
//洗牌,也就是把牌打散,用Collections的shuffle()方法实现
Collections.shuffle(array);
// System.out.println(array);
//发牌,也就是遍历集合,给三个玩家发牌
ArrayList<String> lqxarray = new ArrayList<String>();
ArrayList<String> lyarray = new ArrayList<String>();
ArrayList<String> fqyarray = new ArrayList<String>();
ArrayList<String> dparray = new ArrayList<String>();
for (int i=0; i<array.size();i++){
String poker = array.get(i);
//最后三张牌就存入底牌
if (i>=array.size()-3){
dparray.add(poker);
//存入每轮第三张牌
}else if (i%3==0){
lqxarray.add(poker);
//存入每轮二张牌
}else if (i%3==1){
lyarray.add(poker);
//存入每轮第一张牌
}else if (i%3==2){
fqyarray.add(poker);
}
}
//看牌,也就是三个玩家分别遍历自己的牌
lookPorker("林青霞",lqxarray);
lookPorker("柳岩",lyarray);
lookPorker("风清扬",fqyarray);
lookPorker("底牌",dparray);
}
//看牌的方法
public static void lookPorker(String name,ArrayList<String> array){
System.out.println(name + "的牌是:");
for (String poker :array){
System.out.print(poker +" ");
}
System.out.println();
}
}
林青霞的牌是:
♣Q ♥K ♦A ♠J ♠4 ♣J ♣2 ♦3 ♣9 ♦4 ♥8 大王 ♦6 ♥4 ♥6 ♥9 ♠8
柳岩的牌是:
♦9 ♥7 ♥10 ♣10 ♦J ♣5 ♠K ♠Q ♦10 ♠5 ♣A 小王 ♦2 ♠3 ♣3 ♥5 ♦5
风清扬的牌是:
♠7 ♠2 ♠9 ♠10 ♠A ♦7 ♥2 ♥A ♣6 ♣4 ♦Q ♣7 ♠6 ♦K ♥3 ♥J ♥Q
底牌的牌是:
♣K ♣8 ♦8
案例:模拟斗地主升级版
需求:通过程序实现斗地主中的洗牌,发牌和看牌。要求:对看牌进行排序
HashMap
Key value ArrayLisr 洗牌 TreeSet 看牌
0 ♦2 0 1,5 ♠2,♣3
1 ♠2 1
2 ♥2 2
... ... ... ------>> 2,3 ♥2,♠2
52 小王 52
53 大王 53 0,52 ♦2 ,小王
思路:
-
创建HashMap,键是编号,值是牌
-
创建ArrayList,存储编号
-
创建花色数租和点数数租
-
从0开始往HashMap里面存储编号,并存储对应的牌。同时往ArrayList里面存储编号
-
洗牌(洗的是编号),用Collections的shuffle()方法实现
-
发牌(发的也是编号,为了保证编号是排序的,创建TreeSet(集合接受))
-
定义方法看牌(遍历TreeSet集合,获取编号,看到HashMap集合找对应的牌)
-
调用看牌方法
package Demoxx.demo_014;
/*
需求:通过程序实现斗地主中的洗牌,发牌和看牌。要求:对看牌进行排序
思路:
1. 创建HashMap,键是编号,值是牌
2. 创建ArrayList,存储编号
3. 创建花色数租和点数数租
4. 从0开始往HashMap里面存储编号,并存储对应的牌。同时往ArrayList里面存储编号
5. 洗牌(洗的是编号),用Collections的shuffle()方法实现
6. 发牌(发的也是编号,为了保证编号是排序的,创建TreeSet(集合接受))
7. 定义方法看牌(遍历TreeSet集合,获取编号,看到HashMap集合找对应的牌)
8. 调用看牌方法
*/
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;
public class PokerDemo {
public static void main(String[] args) {
//创建HashMap,键是编号,值是牌
HashMap<Integer,String> hm = new HashMap<Integer,String>();
//创建ArrayList,存储编号
ArrayList<Integer> array = new ArrayList<Integer>();
//创建花色数租和点数数租
String[] colors = {"♦", "♣", "♠", "♥"};
String[] numbers = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"};
//从0开始往HashMap里面存储编号,并存储对应的牌。同时往ArrayList里面存储编号
int index = 0;//定义编号
hm.put(index,"小王");
array.add(index);
index++;
hm.put(index,"大王");
array.add(index);
index++;
for (String number:numbers){
for (String color:colors){
hm.put(index,color+number);
array.add(index);
index++;
}
}
//洗牌(洗的是编号),用Collections的shuffle()方法实现
Collections.shuffle(array);
//发牌(发的也是编号,为了保证编号是排序的,创建TreeSet(集合接受))
TreeSet<Integer> lqxSet = new TreeSet<Integer>();
TreeSet<Integer> lySet = new TreeSet<Integer>();
TreeSet<Integer> fqySet = new TreeSet<Integer>();
TreeSet<Integer> dpSet = new TreeSet<Integer>();
for (int i = 0; i<array.size();i++){
int x = array.get(i);
if (i>=array.size()-3){
dpSet.add(x);
}else if (i%3==0){
lqxSet.add(x);
}else if (i%3==1){
lySet.add(x);
}else if (i%3==2){
fqySet.add(x);
}
}
//调用看牌方法
lookPoker("林青霞",lqxSet,hm);
lookPoker("柳岩",lySet,hm);
lookPoker("风清扬",fqySet,hm);
lookPoker("底牌",dpSet,hm);
}
//定义方法看牌(遍历TreeSet集合,获取编号,看到HashMap集合找对应的牌)
public static void lookPoker(String name,TreeSet<Integer> ts,HashMap<Integer,String> hm){
System.out.print(name+ "的牌是:");
for (Integer key:ts){
String poker = hm.get(key);
System.out.print(poker + " ");
}
System.out.println();
}
}
林青霞的牌是:小王 ♦2 ♥2 ♥A ♣K ♣Q ♠Q ♦J ♣J ♦10 ♥10 ♦9 ♥9 ♣8 ♠7 ♣4 ♥3
柳岩的牌是:♣2 ♦A ♥K ♠J ♥J ♠9 ♦8 ♠8 ♦7 ♦6 ♣6 ♠6 ♥6 ♠5 ♦4 ♥4 ♦3
风清扬的牌是:大王 ♠2 ♣A ♦K ♠K ♦Q ♥Q ♣10 ♣9 ♥8 ♣7 ♥7 ♣5 ♥5 ♠4 ♣3 ♠3
底牌的牌是:♠A ♠10 ♦5

浙公网安备 33010602011771号