Java集合学习
集合一 、集合概述1.1集合类的特点提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变。1.2 集合类体系结构二、Collection集合2.1 Collection集合概述和使用是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现2.2 创建Collection集合的对象多态的方
集合
一 、集合概述
1.1集合类的特点
提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变。
1.2 集合类体系结构
二、Collection集合
2.1 Collection集合概述和使用
- 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
- JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现
2.2 创建Collection集合的对象
- 多态的方式
- 具体的实现类ArrayList
public class CollectionDemo1 {
public static void main(String[] args) {
//Interface Collection<E>
Collection<String> c = new ArrayList<String>();
//添加 add(E e)
c.add("xuanxuan");
c.add("hello");
c.add("world");
System.out.println(c);
}
}
运行结果:
[xuanxuan, hello, world]
2.3 Collection集合常用方法
方法名 | 说明 |
---|---|
boolean add(E e) | 添加元素 |
boolean remove(Object o) | 从集合中移除指定的元素 |
void clear() | 清空集合中的元素 |
boolean contains(Object o) | 判断集合中是否存在指定的元素 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中的元素个数 |
public class CollectionDemo2 {
public static void main(String[] args) {
//Interface Collection<E>
Collection<String> c = new ArrayList<String>();
//添加元素boolean add(E e)
System.out.println(c.add("xuanxuan")); //true
c.add("hello");
c.add("world");
c.add("world");
System.out.println(c);
System.out.println("---------------------------");
//boolean remove(Object o)从集合中移除指定的元素
System.out.println(c.remove("world")); //true
System.out.println(c.remove("java")); //false
System.out.println(c);
System.out.println("---------------------------");
//void clear()清空集合中的元素
// c.clear();
//boolean contains(Object o)判断集合中是否存在指定的元素
System.out.println(c.contains("xuanxuan")); //true
System.out.println("---------------------------");
//boolean isEmpty()判断集合是否为空
System.out.println(c.isEmpty()); //false
System.out.println("---------------------------");
//int size()集合的长度,也就是集合中的元素个数
System.out.println(c.size()); //3
}
}
运行结果:
true
[xuanxuan, hello, world, world]
---------------------------
true
false
[xuanxuan, hello, world]
---------------------------
true
---------------------------
false
---------------------------
3
2.4 Collection集合的遍历
iterator:迭代器,集合的专用遍历方式
- iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
- 迭代器是通过集合的iterator()方法得到的。所以我们说它是依赖于集合而存在的
iterator中的常用方法
- E next():返回迭代中的下一个元素
- boolean hasNext():如果迭代具有更多的元素,则返回true
public class IteratorDemo1 {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("xuanxuan");
c.add("hello");
c.add("world");
//iterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
Iterator<String> iterator = c.iterator();
//E next():返回迭代中的下一个元素
System.out.println(iterator.next());
System.out.println(iterator.next());
System.out.println(iterator.next());
//boolean hasNext():如果迭代具有更多的元素,则返回true
while (iterator.hasNext()){
String s = iterator.next();
System.out.println(s);
}
}
}
小Demo:
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='" + name + '\'' +
", age=" + age +
'}';
}
}
public class CollectionDemo {
public static void main(String[] args) {
Collection<Student> c =new ArrayList<Student>();
Student student1 = new Student("hua1",22);
Student student2 = new Student("hua2",22);
Student student3 = new Student("hua3",22);
c.add(student1);
c.add(student2);
c.add(student3);
Iterator<Student> iterator = c.iterator();
while(iterator.hasNext()){
Student s = iterator.next();
System.out.println(s.getName()+","+s.getAge());
}
}
}
运行结果:
hua1,22
hua2,22
hua3,22
三、List集合
3.1 List集合概述和特点
概述
- 有序集合(也成为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
- 与Set集合不同,列表通常允许重复的元素
特点
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可以重复
3.2 List集合特有方法
方法名 | 说明 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
public class ListDemo2 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
//添加集合元素
list.add("xuanxuan");
list.add("hello");
list.add("world");
list.add("world");
//输出集合对象
System.out.println(list);
System.out.println("---------------------------");
//void add(int index,E element)在此集合中的指定位置插入指定的元素
list.add(1,"java");
System.out.println(list);
System.out.println("---------------------------");
//E remove(int index)删除指定索引处的元素,并返回被删除的元素
System.out.println(list.remove(1));
System.out.println(list);
System.out.println("---------------------------");
//E set(int index,E element)修改指定索引处的元素,返回被修改的元素
list.set(3,"java");
System.out.println(list);
System.out.println("---------------------------");
//E get(int index)返回指定索引处元素
System.out.println("---------------------------");
//复习迭代器遍历
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("---------------------------");
//for循环
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
}
}
运行结果:
[xuanxuan, hello, world, world]
---------------------------
[xuanxuan, java, hello, world, world]
---------------------------
java
[xuanxuan, hello, world, world]
---------------------------
[xuanxuan, hello, world, java]
---------------------------
xuanxuan
---------------------------
xuanxuan
hello
world
java
---------------------------
xuanxuan
hello
world
java
练习:
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='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ListDemo {
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>();
Student student1 = new Student("xuanxuan1",22);
Student student2 = new Student("xuanxuan2",22);
Student student3 = new Student("xuanxuan3",22);
list.add(student1);
list.add(student2);
list.add(student3);
//迭代器
Iterator<Student> iterator = list.iterator();
while ( iterator.hasNext()) {
Student s = iterator.next();
System.out.println(s.getName()+","+s.getAge());
}
System.out.println("---------------------------");
//for循环
for (int i = 0; i < list.size(); i++) {
Student s2 = list.get(i);
System.out.println(s2.getName()+","+s2.getAge());
}
}
}
运行结果:
xuanxuan1,22
xuanxuan2,22
xuanxuan3,22
---------------------------
xuanxuan1,22
xuanxuan2,22
xuanxuan3,22
3.3 并发修改异常
- ConcurrentModificationException
- 迭代器遍历过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际值不一致
public class ListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("java");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()){
String s = iterator.next();
if (s.equals("world")){
list.add("xuanxuan");
}
}
//Exception in thread "main" java.util.ConcurrentModificationException
System.out.println(list);
}
}
3.4 ListIterator
ListIterator:列表迭代器
- 通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
- 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
ListIterator中的常用方法:
方法名 | 说明 |
---|---|
E next() | 返回迭代中的下一个元素 |
Boolean hasNext() | 如果迭代具有更多元素,则返回true |
E previous() | 返回列表中的上一个元素 |
boolean hasPrevious() | 如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true |
void add(E e) | 将指定的元素插入列表 |
3.5 增强for循环
增强for:简化数组和Collection集合的遍历
- 实现Iterable接口的类允许其对象成为增强型for语句的目标
- 它是JDK之后出现的,其内部原理是一个Iterator迭代器
增强for的格式
- 格式:
for(元素的数据类型 变量名 : 数组或者Collection集合){
//在此处使用变量即可,该变量就是元素
}
public class ListDemo {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
for (int i:arr) {
System.out.println(i);
}
System.out.println("---------------------------");
String[] strArray = new String[]{"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 l : list){
System.out.println(l);
}
}
}
运行结果:
1
2
3
4
5
---------------------------
hello
world
java
---------------------------
hello
world
java
3.6 List集合存储学生对象三种遍历方式
学生对象:
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='" + name + '\'' +
", age=" + age +
'}';
}
}
实现:
public class ListDemo5 {
public static void main(String[] args) {
List<Student> list = new ArrayList<Student>();
Student student1 = new Student("xuanxuan1",22);
Student student2 = new Student("xuanxuan2",22);
Student student3 = new Student("xuanxuan3",22);
list.add(student1);
list.add(student2);
list.add(student3);
//Iterator迭代器
ListIterator<Student> listIterator = list.listIterator();
while (listIterator.hasNext()){
Student s1 = listIterator.next();
System.out.println(s1.getName()+","+s1.getAge());
}
System.out.println("---------------------------");
//for循环
for (int i = 0; i < list.size(); i++) {
Student s2 = list.get(i);
System.out.println(s2.getName()+","+s2.getAge());
}
System.out.println("---------------------------");
//增强for
for (Student s3 : list) {
System.out.println(s3.getName()+","+s3.getAge());
}
}
}
运行结果:
xuanxuan1,22
xuanxuan2,22
xuanxuan3,22
---------------------------
xuanxuan1,22
xuanxuan2,22
xuanxuan3,22
---------------------------
xuanxuan1,22
xuanxuan2,22
xuanxuan3,22
3.7 List集合子类特点
-
LIst集合常用子类:ArrayList、LinkedList
-
ArrayList:底层数据结构是数组,查询快、增删慢
-
LinkedList:底层数据结构是链表,查询慢、增删快
public class ListDemo {
public static void main(String[] args) {
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add("hello");
arrayList.add("world");
arrayList.add("java");
for (String s : arrayList) {
System.out.println(s);
}
System.out.println("---------------------------");
LinkedList<String> linkedList = new LinkedList<String>();
linkedList.add("hello");
linkedList.add("world");
linkedList.add("java");
for (String s : linkedList) {
System.out.println(s);
}
}
}
运行结果:
hello
world
java
---------------------------
hello
world
java
3.8 ArrayList集合存储学生对象三种遍历方式
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='" + name + '\'' +
", age=" + age +
'}';
}
}
public class ListDemo {
public static void main(String[] args) {
ArrayList<Student> arrayList = new ArrayList<Student>();
Student student1 = new Student("xuanxuan1",22);
Student student2 = new Student("xuanxuan2",22);
Student student3 = new Student("xuanxuan3",22);
arrayList.add(student1);
arrayList.add(student2);
arrayList.add(student3);
Iterator<Student> iterator = arrayList.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
System.out.println("---------------------------");
for (int i = 0; i < arrayList.size(); i++) {
System.out.println(arrayList.get(i));
}
System.out.println("---------------------------");
for (Student student : arrayList) {
System.out.println(student);
}
}
}
3.9 LinkedList集合的特有功能
方法名 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
public class ListDemo8 {
public static void main(String[] args) {
LinkedList<String> linkedList = new LinkedList<String>();
linkedList.add("hello");
linkedList.add("world");
linkedList.add("java");
System.out.println(linkedList);
System.out.println("---------------------------");
//public void addFirst(E e)在该列表开头插入指定的元素
linkedList.addFirst("javaee");
System.out.println(linkedList);
System.out.println("---------------------------");
//public void addLast(E e)将指定的元素追加到此列表的末尾
linkedList.addLast("xuanxuan");
System.out.println(linkedList);
System.out.println("---------------------------");
//public E getFirst()返回此列表中的第一个元素
System.out.println(linkedList.getFirst());
System.out.println("---------------------------");
//public E getLast()返回此列表中的最后一个元素
System.out.println(linkedList.getLast());
System.out.println("---------------------------");
//public E removeFirst()从此列表中删除并返回第一个元素
System.out.println(linkedList.removeFirst());
System.out.println("---------------------------");
//public E removeLast()从此列表中删除并返回最后一个元素
System.out.println(linkedList.removeLast());
}
}
运行结果:
[hello, world, java]
---------------------------
[javaee, hello, world, java]
---------------------------
[javaee, hello, world, java, xuanxuan]
---------------------------
javaee
---------------------------
xuanxuan
---------------------------
javaee
---------------------------
xuanxuan
四、Set集合
4.1 Set集合概述和特点
概述:
- 不包含重复元素的集合
特点:
- 不包含重复元素的集合
- 没有带索引的方法,所以不能使用普通的for循环遍历
实现类HashSet
- 对集合的迭代顺序不作任何保证
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("java");
for (String s : set) {
System.out.println(s);
}
}
}
运行结果:
world
java
hello
4.2 哈希值概述和特点
概述:
- 是JDK根据对象的地址或者字符串或者数字算出来的
int类型
的数值
Object类中有一个方法可以获取对象的哈希值
public int hashCode():返回对象的哈希码值
特点:
- 同一个对象多次调用hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同得。而重写hashCode()方法,可以实现让不同对象的哈希值相同
public class HashDemo {
public static void main(String[] args) {
Student s1 = new Student("xuanxuan",22);
System.out.println(s1.hashCode());
System.out.println(s1.hashCode());
System.out.println("---------------------------");
Student s2 = new Student("xuanxuan",22);
System.out.println(s2.hashCode());
System.out.println("---------------------------");
System.out.println("hello".hashCode());
System.out.println("world".hashCode());
System.out.println("java".hashCode());
System.out.println("---------------------------");
System.out.println("world".hashCode());
System.out.println("---------------------------");
System.out.println("你好".hashCode());
System.out.println("世界".hashCode());
}
}
运行结果:
460141958
460141958
---------------------------
1163157884
---------------------------
99162322
113318802
3254818
---------------------------
113318802
---------------------------
652829
649718
4.3 HashSet集合概述和特点
HashSet集合特点:
- 底层数据接口是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是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
4.4 HashSet集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储多个学生对象,使用程序实现控制台遍历该集合。
要求:学生对象的成员变量值相同,我们就认微是同一个对象
public class SetDemo4 {
public static void main(String[] args) {
Set<Student> set = new HashSet<Student>();
Student s1 = new Student("xuanxuan1",22);
Student s2 = new Student("xuanxuan2",23);
Student s3 = new Student("xuanxuan3",24);
Student s4 = new Student("xuanxuan3",24);
set.add(s1);
set.add(s2);
set.add(s3);
set.add(s4);
for (Student student : set) {
System.out.println(student.getName()+","+student.getAge());
}
}
}
运行结果:
xuanxuan1,22
xuanxuan2,23
xuanxuan3,24
4.5 LinkedHashSet集合概述和特点
LinkedHashSet集合特点
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复的元素
public class SetDemo {
public static void main(String[] args) {
LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();
linkedHashSet.add("hello");
linkedHashSet.add("world");
linkedHashSet.add("java");
linkedHashSet.add("java");
for (String s : linkedHashSet) {
System.out.println(s);
}
}
}
运行结果:
hello
world
java
4.6 TreeSet集合概述和特点
TreeSet集合的特点:
- 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
TreeSet():根据其元素的自然排序进行排序
TreeSet(Comparator comparator):根据指定的比较器进行排序
- 没有带索引的方法,所以不能使用普通for循环遍历
public class SetDemo {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<Integer>();
ts.add(10);
ts.add(22);
ts.add(40);
ts.add(55);
ts.add(31);
ts.add(40);
for (Integer t : ts) {
System.out.println(t);
}
}
}
10
22
31
40
55
4.7 自然排序Comparable的使用
- 存储学生对象并遍历,创建TreeSet集合并使用无参构造方法
- 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
结论:
- 用TreeSet集合存储自定义对象,无参构造方法使用得是自然排序对元素进行排序的
- 自然排序,就是让元素所属的类实现Comparable接口,重写CompareTo(T o)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
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='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student s) {
// return 0;
// return -1;
int i = this.age - s.age;
int num = i==0?this.name.compareTo(s.name):i;
return num;
}
}
public class SetDemo {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<Student>();
Student s1 = new Student("xuanxuan",22);
Student s2 = new Student("huaxuan",25);
Student s3 = new Student("zhangsan",23);
Student s4 = new Student("lisi",29);
Student s5 = new Student("awu",29);
Student s6 = new Student("awu",29);
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
treeSet.add(s6);
for (Student student : treeSet) {
System.out.println(student.getName()+","+student.getAge());
}
}
}
运行结果:
xuanxuan,22
zhangsan,23
huaxuan,25
awu,29
lisi,29
4.8 比较器排序Comparator的使用
- 存储学生对象并遍历,创建TreeSet集合使用带参构造方法
- 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
结论:
-
用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
-
比较器排序,就是让集合构造方法接受Comparator的实现类对象,重写compare(T o1,T o2)
-
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
public class SetDemo {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<Student>(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;
}
});
Student s1 = new Student("xuanxuan",22);
Student s2 = new Student("huaxuan",25);
Student s3 = new Student("zhangsan",23);
Student s4 = new Student("lisi",29);
Student s5 = new Student("awu",29);
Student s6 = new Student("awu",29);
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
treeSet.add(s6);
for (Student student : treeSet) {
System.out.println(student.getName()+","+student.getAge());
}
}
}
练习1:
- 需求:用TreeSet集合存储多个学生信息(姓名、语文成绩、数学成绩),并遍历该集合的
- 要求:按照总分从高到底出现
public class 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;
}
}
public class SetDemo {
public static void main(String[] args) {
TreeSet<Student> treeSet = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
// int score = (s2.getChinese() + s2.getMath()) - (s1.getChinese() + s1.getMath());
int score = s2.getSum() - s1.getSum();
int score2 = score == 0 ? s1.getChinese() - s2.getChinese() : score;
int score3 = score == 0 ? s1.getMath() - s2.getMath() : score2;
int score4 = score == 0 ? s1.getName().compareTo(s2.getName()) : score3;
return score4;
}
});
Student s1 = new Student("xuanxuan",100,100);
Student s2 = new Student("huaxuan",100,100);
Student s3 = new Student("zhangsan",98,86);
Student s4 = new Student("lisi",79,99);
Student s5 = new Student("awu",89,75);
Student s6 = new Student("xueba",100,100);
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
treeSet.add(s5);
treeSet.add(s6);
for (Student student : treeSet) {
System.out.println(student.getName()+","+student.getChinese()+","+student.getMath()+","+student.getSum());
}
}
}
运行结果:
huaxuan,100,100,200
xuanxuan,100,100,200
xueba,100,100,200
zhangsan,98,86,184
lisi,79,99,178
awu,89,75,164
练习2:
- 需求:编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并在控制台输出
public class SetDemo {
public static void main(String[] args) {
Set<Integer> set = new TreeSet<Integer>();
Random random = new Random(20);
for (int i = 0; set.size() < 10; i++) {
int num = random.nextInt(20) + 1;
set.add(num);
}
System.out.println(set);
}
}
运行结果:
[2, 3, 5, 6, 7, 9, 11, 14, 16, 17]
五、泛型
5.1 泛型概述
概述:
- 是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型
- 它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数
参数化类型:
- 将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型
- 这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法和泛型接口
泛型定义格式:
- <类型>:指定一种类型的格式。这里的类型可以看成是形参
- <类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参
- 将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能时引用数据类型
泛型的好处:
- 把运行时期的问题提前到了编译期间
- 避免了强制类型转换
public class GenericDemo {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("hello");
c.add("world");
c.add("java");
Iterator<String> iterator = c.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
5.2 泛型类
public class Generic<T>{
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
public class GenericDemo {
public static void main(String[] args) {
Generic<String> g1 = new Generic<String>();
g1.setT("xuanxuan");
System.out.println(g1.getT());
Generic<Integer> g2 = new Generic<Integer>();
g2.setT(22);
System.out.println(g2.getT());
Generic<Boolean> g3 = new Generic<Boolean>();
g3.setT(true);
System.out.println(g3.getT());
}
}
运行结果:
xuanxuan
22
true
5.3 泛型方法
public class Generic<T> {
public void show(T t){
System.out.println(t);
}
}
public class GenericDemo {
public static void main(String[] args) {
Generic g = new Generic();
g.show("xuanxuan");
g.show(22);
g.show(true);
}
}
5.4 泛型接口
泛型接口的定义格式:
- 格式:修饰符interface 接口名<类型>{}
public interface Generic<T>{}
public interface Generic<T> {
void show(T t);
}
public class GenericImpl<T> implements Generic<T>{
@Override
public void show(T t) {
System.out.println(t);
}
}
public class GenericDemo {
public static void main(String[] args) {
Generic<String> g1 = new GenericImpl<String>();
g1.show("xuanxuan");
}
}
5.5 类型通配符
为了表示各种泛型List的父类,可以使用类型通配符
- 类型通配符:<?>
- List<?>:表示元素类型未知的List的父类,并不能把元素添加到其中
- 这种带通配符的List仅表示它是各种泛型List的父类,并不能把元素添加到其中
如果说我们不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型List的父类,可以使用类型通配符的上限
- 类型通配符上限:<?extends类型>
- List<?extends Number>:它表示的类型是Number或者其子类型
除了可以指定类型通配符上限,我们也可以指定类型通配符的下限
- 类型通配符下限:<?super类型>
- List<?super Number>:它表示的类型是Number或者其父类型
public class GenericDemo {
public static void main(String[] args) {
//类型通配符:<?>
List<?> list1 = new ArrayList<Object>();
List<?> list2 = new ArrayList<Number>();
List<?> list3 = new ArrayList<Integer>();
//类型通配符上限:<?extends类型>
List<? extends Number> list4 = new ArrayList<Number>();
List<? extends Number> list5 = new ArrayList<Integer>();
//List<?super Number>:它表示的类型是Number或者其父类型
List<? super Number> list6 = new ArrayList<Number>();
List<? super Number> list7 = new ArrayList<Object>();
}
}
5.6 可变参数
可变参数又称参数个数可变,用作方法的形参出现,那么方法参数个数就是可变的了
- 格式:修饰符 返回值类型 方法名(数据类型…变量名){}
- 范例:public static int sum(int…a){}
可变参数注意事项
- 这里的变量其实是一个数组
- 如果一个方法有多个参数,包含可变参数,可变参数要放在最后
public class ArgsDemo {
public static void main(String[] args) {
System.out.println(sum(10, 20, 30, 50, 60, 70, 80, 90, 100));
}
public static int sum(int...a){
int sum = 0;
for (int i : a) {
sum += i;
}
return sum;
}
}
5.7 可变参数的使用
Arrays工具类中有一个静态方法:
- public static List asList(T…a):返回由指定数组支持的固定大小的列表
- 返回的集合不能做增删操作,可以做修改操作
List接口中有一个静态方法:
- public static list of(E…elements):返回包含任意数量元素的不可变列表
- 返回的集合不能做增删改操作
Set接口中有一个静态方法:
- public static Set of(E…elements):返回一个包含任意数量元素的不可变集合
- 返回的集合不能做增删操作,没有修改的方法
public class GenericDemo {
public static void main(String[] args) {
//Arrays工具类中有一个静态方法:public static <T> List<T> asList(T...a):返回由指定数组支持的固定大小的列表
List<String> list1 = Arrays.asList("hello","world","java");
// list1.add("javaee"); //UnsupportedOperationException
// list1.remove("java"); //UnsupportedOperationException
list1.set(2,"javaee");
System.out.println(list1);
}
}
六、Map集合
6.1 Map集合概述和使用
Map集合概述
- Interface Map<K,V> K:键的类型 V:值的类型
- 将键映射到值的对象;不能包含重复的键;每个键可以映射找到最多一个值
- 举例:编号和姓名
id001 xuanxuan1
id002 xuanxuan2
id003 xuanxuan3
创建Map集合的对象
- 多态的方式
- 具体的实现类HashMap
public class MapDemo {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("id001","xuanxuan1");
map.put("id002","xuanxuan2");
map.put("id003","xuanxuan3");
map.put("id003","xuanxuan4");
System.out.println(map);
}
}
运行结果:
{id002=xuanxuan2, id001=xuanxuan1, id003=xuanxuan4}
6.2 Map集合的基本功能
方法名 | 说明 |
---|---|
V put(K key,V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 移除所有的键值对元素 |
boolean containsKey(Object key) | 判断集合是否包含指定的键 |
boolean containValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
public class mapDemo2 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
//添加元素:V put(K key,V value)
map.put("id001","xuanxuan1");
map.put("id002","xuanxuan2");
map.put("id003","xuanxuan3");
System.out.println(map);
System.out.println("---------------------------");
//根据键删除键值对元素:V remove(Object key)
System.out.println(map.remove("id002"));
System.out.println(map.remove("id004"));
System.out.println(map);
//移除所有的键值对元素:void clear()
System.out.println("---------------------------");
// map.clear();
// System.out.println(map);
//判断集合是否包含指定的键:boolean containsKey(Object key)
System.out.println(map.containsKey("id002"));
System.out.println(map.containsKey("id003"));
System.out.println("---------------------------");
//判断集合是否包含指定的值:boolean containValue(Object value)
System.out.println(map.containsValue("xuanxuan1"));
System.out.println("---------------------------");
//判断集合是否为空:boolean isEmpty()
System.out.println(map.isEmpty());
System.out.println("---------------------------");
//集合的长度,也就是集合中键值对的个数:int size()
System.out.println(map.size());
System.out.println(map);
}
}
运行结果:
{id002=xuanxuan2, id001=xuanxuan1, id003=xuanxuan3}
---------------------------
xuanxuan2
null
{id001=xuanxuan1, id003=xuanxuan3}
---------------------------
false
true
---------------------------
true
---------------------------
false
---------------------------
2
{id001=xuanxuan1, id003=xuanxuan3}
6.3 Map集合的获取功能
方法名 | 说明 |
---|---|
V get(Object key) | 根据键获取值 |
Set KeySet() | 获取所有键的集合 |
Collection values() | 获取所有值的集合 |
Set<Map.Entry<K,V>> entrySet() | 获取所有键值对对象的集合 |
public class MapDemo3 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("id001","xuanxuan1");
map.put("id002","xuanxuan2");
map.put("id003","xuanxuan3");
//根据键获取值:V get(Object key)
System.out.println(map.get("id001"));
//获取所有键的集合:Set<K> KeySet()
System.out.println(map.keySet());
//获取所有值的集合:Collection<V> values()
System.out.println(map.values());
//获取所有键值对对象的集合:Set<Map.Entry<K,V>> entrySet()
System.out.println(map.entrySet());
}
}
运行结果:
xuanxuan1
[id002, id001, id003]
[xuanxuan2, xuanxuan1, xuanxuan3]
[id002=xuanxuan2, id001=xuanxuan1, id003=xuanxuan3]
6.4 Map集合的遍历
方法一:
- 获取所有键的集合,用keySet()方法实现
- 遍历键的集合,获取到每一个键,用增强for实现
- 根据键去找值,用get(Object key)方法实现
public class MapDemo4 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("id001","xuanxuan1");
map.put("id002","xuanxuan2");
map.put("id003","xuanxuan3");
Set<String> key = map.keySet();
for (String k : key) {
String v = map.get(k);
System.out.println(v);
}
}
}
方法二:
- 获取map所有键值对对象的集合
- 遍历键值对对象的集合,得到每一个键值对对象
- 根据键值对对象获取键和值
public class MapDemo5 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("id001", "xuanxuan1");
map.put("id002", "xuanxuan2");
map.put("id003", "xuanxuan3");
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for (Map.Entry<String, String> entry : entrySet) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "," + value);
}
}
}
6.5 HashMap集合存储学生对象并遍历
需求1:创建一个HashMap集合,键是学号(String),值是学生对象(Student)。存储三个键值对元素,并遍历。
public class MapDemo6 {
public static void main(String[] args) {
Map<String, Student> map = new HashMap<String, Student>();
Student s1 = new Student("xuanxuan1", 22);
Student s2 = new Student("xuanxuan2", 23);
Student s3 = new Student("xuanxuan3", 24);
map.put("xuehao001", s1);
map.put("xuehao002", s2);
map.put("xuehao003", s3);
Set<String> key = map.keySet();
for (String key1 : key) {
Student value = map.get(key1);
System.out.println(value.getName() + "," + value.getAge());
}
System.out.println("--------------------------------------");
Set<Map.Entry<String, Student>> entrySet = map.entrySet();
for (Map.Entry<String, Student> entry : entrySet) {
String key2 = entry.getKey();
Student value2 = entry.getValue();
System.out.println(key2 + "," + value2.getName() + "," + value2.getAge());
}
}
}
需求2:创建一个HashMap集合,键是学生对象(Student),值是居住地(String)。存储多个键值对元素,并遍历。要求保证键的唯一性:如果学生对象的成员变量值相同,我们就认为是同一个对象。
public class MapDemo7 {
public static void main(String[] args) {
Map<Student, String> map = new HashMap<Student, String>();
Student s1 = new Student("xuanxuan1", 22);
Student s2 = new Student("xuanxuan2", 23);
Student s3 = new Student("xuanxuan3", 24);
Student s4 = new Student("xuanxuan3", 24);
map.put(s1, "北京");
map.put(s2, "天津");
map.put(s3, "河北");
map.put(s3, "南京");
Set<Student> keySet = map.keySet();
for (Student key : keySet) {
String value = map.get(key);
System.out.println(key.getName() + "," + key.getAge() + "," + value);
}
}
}
运行结果:
xuanxuan1,22,北京
xuanxuan2,23,天津
xuanxuan3,24,南京
6.6 集合嵌套之HashMap嵌套ArrayList
需求:创建一个HashMap集合,存储三个键值对元素,每一个键值对元素的键是String,值是ArrayList,每一个ArrayList的元素是String,并遍历
public class MapDemo8 {
public static void main(String[] args) {
HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
ArrayList<String> arrayList1 = new ArrayList<String>();
arrayList1.add("李白");
arrayList1.add("白起");
map.put("人物", arrayList1);
ArrayList<String> arrayList2 = new ArrayList<String>();
arrayList2.add("黑色");
arrayList2.add("白色");
map.put("颜色", arrayList2);
ArrayList<String> arrayList3 = new ArrayList<String>();
arrayList3.add("东西");
arrayList3.add("南北");
map.put("方向", arrayList3);
Set<String> keySet = map.keySet();
for (String key : keySet) {
System.out.println(key);
ArrayList<String> value = map.get(key);
for (String s : value) {
System.out.println("\t" + s);
}
}
}
}
运行结果:
颜色
黑色
白色
方向
东西
南北
人物
李白
白起
6.7 统计字符串中每个字符出现的次数
需求:键盘录入一个字符串,要求统计字符串每个字符串出现的次数。
比如:输入abcabcabc 输出:a(3)b(3)c(3)
public class MapDemo9 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个字符串:");
String s = scanner.nextLine();
TreeMap<Character, Integer> hashMap = new TreeMap<Character, Integer>();
for (int i = 0; i < s.length(); i++) {
char key = s.charAt(i);
Integer value = hashMap.get(key);
if (value == null){
hashMap.put(key,1);
}else {
value++;
hashMap.put(key,value);
}
}
StringBuilder stringBuilder = new StringBuilder();
Set<Character> keySet = hashMap.keySet();
for (Character key : keySet) {
Integer value = hashMap.get(key);
stringBuilder.append(key).append("(").append(value).append(")");
}
String result = stringBuilder.toString();
System.out.println(result);
}
}
七、Collections集合
7.1 Collections概述和使用
概述:
- 是针对集合操作的工具类
常用方法:
方法名 | 说明 |
---|---|
public static <T extends Comparable<? super>> void sort(List list) | 将指定的列表按升序排序 |
public static void reverse(List<?> list) | 反转指定列表中元素的顺序 |
public static void shuffle(List<?> list) | 使用默认的随机源随机排列指定的列表 |
public class CollectionsDemo {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.add(30);
list.add(50);
list.add(40);
list.add(20);
list.add(10);
System.out.println(list);
System.out.println("--------------------------------");
Collections.sort(list);
System.out.println(list);
System.out.println("--------------------------------");
Collections.reverse(list);
System.out.println(list);
System.out.println("--------------------------------");
Collections.shuffle(list);
System.out.println(list);
}
}
运行结果:
[30, 50, 40, 20, 10]
--------------------------------
[10, 20, 30, 40, 50]
--------------------------------
[50, 40, 30, 20, 10]
--------------------------------
[10, 30, 20, 40, 50]
7.2 ArrayList存储对象并排序
需求:ArrayList存储学生对象,使用Collections对ArrayList进行排序
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
public class CollectionsDemo2 {
public static void main(String[] args) {
ArrayList<Student> arrayList = new ArrayList<Student>();
Student s1 = new Student("zhangsan",24);
Student s2 = new Student("lisi",23);
Student s3 = new Student("wangwu",23);
Student s4 = new Student("liuliu",24);
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
arrayList.add(s4);
Collections.sort(arrayList, 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 student : arrayList) {
System.out.println(student.getName()+","+student.getAge());
}
}
}
7.3 模拟斗地主
需求:通过程序实现斗地主过程中的洗牌、发牌和看牌
public class CollectionsDemo3 {
public static void main(String[] args) {
HashMap<Integer,String> map = new HashMap<Integer,String>();
ArrayList<Integer> arrayList = new ArrayList<Integer>();
String[] colors = new String[]{"♦", "♠", "♥", "♣"};
String[] numbers = new String[]{"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A","2"};
int index = 0;
for (String number : numbers) {
for (String color : colors) {
map.put(index,color+number);
arrayList.add(index);
index++;
}
}
map.put(index,"小王");
arrayList.add(index);
index++;
map.put(index,"大王");
arrayList.add(index);
Collections.shuffle(arrayList);
TreeSet<Integer> player1 = new TreeSet<Integer>();
TreeSet<Integer> player2 = new TreeSet<Integer>();
TreeSet<Integer> player3 = new TreeSet<Integer>();
TreeSet<Integer> dipai = new TreeSet<Integer>();
for (int i = 0; i < arrayList.size(); i++) {
int x = arrayList.get(i);
if (i >= arrayList.size() - 3) {
dipai.add(x);
} else if (i % 3 == 0) {
player1.add(x);
} else if (i % 3 == 1) {
player2.add(x);
} else if (i % 3 == 2) {
player3.add(x);
}
}
showPoker("player1",player1,map);
showPoker("player2",player2,map);
showPoker("player3",player3,map);
showPoker("底牌",dipai,map);
}
public static void showPoker(String name,TreeSet<Integer> treeSet,HashMap<Integer,String> map){
System.out.print(name + "的牌是:");
for (Integer key : treeSet) {
String poker = map.get(key);
System.out.print(poker+" ");
}
System.out.println();
}
}
前进的道路是坎坷的,愿你做一个无畏的勇士,采撷最美丽的花朵。
更多推荐
所有评论(0)