Java集合框架超详细笔记
1. 集合的引入_对象数组
能够存储对象的一个数组;
需求:有5个学生,都有姓名和年龄,现需要将5个学生存储到数组中,并遍历5个学生信息;
1)首先得自定义一个学生类 Student(name姓名,age年龄)
2)定义一个数组(对象数组)---->学生数组
3)创建5个学生对象
4)将s1到s5存储到数组中
5)遍历学生对象,输出每一个学生的姓名和年龄;
//学生类
public class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", 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;
}
}
public static void main(String[] args) {
//定义一个学生数组
Student student[] = new Student[5];
//创建学生对象
Student s1 = new Student("卡卡1",23);
Student s2 = new Student("卡卡2",20);
Student s3 = new Student("卡卡3",21);
Student s4 = new Student("卡卡4",24);
Student s5 = new Student("卡卡5",26);
//将学生对象插入数组
student[0] = s1;
student[1] = s2;
student[2] = s3;
student[3] = s4;
student[4] = s5;
//遍历学生数组
for(int i = 0; i < student.length; i++){
Student s = student[i] ;
System.out.println(s.getName()+"---"+s.getAge());
}
}
- 因为学生存在增删改查行为,数组虽然可以存储多个对象但是长度是固定的,不符合长度可变的要求因此引入集合的概念;
2. 集合的概念
概念:对象的容器,存储对象的对象可以代替数组;面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java提供了集合类;
特点:
- 容器的工具类,定义了对多个对象进行操作的常用方法。
位置:java.util.*; 里面。
集合和数组的区别:
长度的区别
数组:长度是固定的;
集合:长度是可变的;
内容的区别
数组:只能存储同一种数据类型 int[] arr = new int[5];
集合:只能存储一种数据类型;
存储数据类型问题
数组:既可以存储基本数据类型,又可以存储引用数据类型;
集合:只能存储引用数据类型;
- 数组:length属性
- String:存在length()方法
- 集合:size()方法
3. Collection接口
Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的;
JDK不提供此接口的任何直接实现:它提供更具体的子接口(如 Set 和 List)实现子实现类,接口不能实例化;
3.1 Collection的基本功能
- boolean add(Object e):添加任意类型的元素
- boolean remove(Object o):删除指定的元素
- void clear() : 暴力删除(删除集合中的所有元素)
- boolean contains(Object o) :是否包含指定的元素,如果包含,返回true
- boolean isEmpty():判断集合是否为空
- int size():获取集合的元素数
public static void main(String[] args) {
//提供子接口实现
Collection c = new ArrayList();
//添加任意类型的元素
c.add("hello");
c.add("java");
c.add("123");
//删除指定的元素
System.out.println(c.remove("hello"));
//暴力删除(删除集合中的所有元素)
c.clear();
//是否包含指定的元素,如果包含,返回true
System.out.println("contains():" + c.contains("kaka"));//false
System.out.println("contains():" + c.contains("123"));//true
//判断是否为空
System.out.println("isEmpty():" + c.isEmpty());//返回Boolean类型
//获取集合的元素数
System.out.println("size():" + c.size());//3
}
}
3.2 Collection的高级功能
boolean addAll(Collection c):添加一个集合中的所有元素
boolean removeAll(Collection c):删除集合中所有元素(该元素一定是在另一集合中也包含的)------>删除一个集合中元素算删除
boolean containsAll(Collection c):一个集合中 包含指定 集合 中的所有元素(包含所有算包含)
boolean retainAll(Collection c):一个集合对另一个集合取交集
如果一个集合A对一个集合B取交集,交集的元素保存在A集合中,B集合不变的
返回值boolean表达的意思A集合中的元素,是否发生变化,如果没有发生变化,
返回false;如果变化,返回true;
public static void main(String[] args) {
//创建两个Collection集合
Collection<String> c1 = new ArrayList<String>();
Collection<String> c2 = new ArrayList<String>();
//添加元素
c1.add("kaka1") ;
c1.add("kaka2") ;
c1.add("kaka3") ;
c1.add("kaka4") ;
c2.add("kaka1") ;
c2.add("kaka2") ;
c2.add("kaka3") ;
c2.add("kaka4") ;
c2.add("kaka5") ;
c2.add("kaka6") ;
System.out.println("c1:"+c1);
System.out.println("c2:"+c2);
//添加一个集合中的所有元素
System.out.println("addAll():" + c1.addAll(c2));
//删除集合中所有元素(该元素一定是在另一集合中也包含的)
System.out.println("removeAll():"+c1.removeAll(c2));
//一个集合中包含指定集合中的所有元素(包含所有算包含)
System.out.println("containsAll():"+c1.containsAll(c2));//false
System.out.println("containsAll():"+c2.containsAll(c1));//true
//一个集合对另一个集合取交集
System.out.println("retainAll():"+c1.retainAll(c2));//没有发生变化false
System.out.println("retainAll():"+c2.retainAll(c1));//发生变化true
System.out.println("c1:"+c1);
System.out.println("c2:"+c2);
}
3.3 集合转对象数组遍历
- Object[] toArray():将集合转换成对象数组
给集合中添加字符串数据并遍历;
public static void main(String[] args) {
//创建一个集合对象
Collection<String> c = new ArrayList<String>();
//给集合中添加元素
c.add("kaka");
c.add("hello");
c.add("java");
//Object[] toArray();
//里面存储的字符串数据----相当于:Object[] objs = new String()
Object[] obj = c.toArray();
//遍历数组
for(int i = 0; i < obj.length; i++){
String s = (String)obj[i];
System.out.println(s + "---" + s.length());
}
}
3.3.1 Object[] toArray遍历案例_01
需求:有5个学生,都有姓名和年龄,现需要将5个学生存储到集合中,并遍历5个学生信息
1)定义一个学生类
2)创建集合对象 Collection
3)创建5个学生
5)将5个学生添加到集合中
6)将集合转换成Object[] toArray
7)遍历数组
//Student类
public class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
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 Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
public static void main(String[] args) {
//创建集合对象
Collection<Student> c = new ArrayList<Student>();
//创建对象
Student s1 = new Student("卡卡",23);
Student s2 = new Student("张三",23);
Student s3 = new Student("李四",23);
Student s4 = new Student("王五",23);
Student s5 = new Student("赵六",23);
//集合中添加元素
c.add(s1);
c.add(s2);
c.add(s3);
c.add(s4);
c.add(s5);
//将集合转换为object[]数组
Object[] obj = c.toArray();
//遍历数组
for(int i = 0; i < obj.length; i++){
Student s = (Student)obj[i];
System.out.println(s.getName() + "---" +s.getAge());
}
}
3.4 集合的专有遍历方式_迭代器
迭代器遍历:
Iterator iterator():获取集合的迭代器(集合专用遍历方式)
Iterator:迭代器(接口)
Object next() :获取下一个元素------>是对 Object[] toArray()这个方法封装
(是通过ArrayList集合实现的(内部类)next())
boolean hasNext():判断功能,判断是否有下一个元素
迭代器的使用步骤:
创建集合对象
给集合对象中添加元素
获取迭代器
3.1 判断当前迭代器是否有下一个可以遍历的元素
3.2 在获取下一个元素
public static void main(String[] args) {
//创建集合对象
Collection<String> c = new ArrayList<String>();
//给集合中添加字符串元素
c.add("kaka");
c.add("hello");
c.add("java");
//使用迭代器遍历
Iterator<String> it = c.iterator();
while(it.hasNext()){
//向下转型
String s = (String)(it.next());
System.out.println(s + "---" + s.length());
}
}
3.4.1 迭代器遍历案例_02
需求:有5个学生,都有姓名和年龄,现需要将5个学生存储到集合中,并遍历5个学生信息
1)定义一个学生类
2)创建集合对象 Collection
3)创建5个学生
5)将5个学生添加到集合中
6)创建迭代器
7)利用迭代器遍历集合
/*
* 学生类
*/
public class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
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 Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
}
public static void main(String[] args) {
//创建集合对象
Collection<Student> c = new ArrayList<Student>();
//创建对象
Student s1 = new Student("卡卡",23);
Student s2 = new Student("张三",23);
Student s3 = new Student("李四",23);
Student s4 = new Student("王五",23);
Student s5 = new Student("赵六",23);
//集合中添加元素
c.add(s1);
c.add(s2);
c.add(s3);
c.add(s4);
c.add(s5);
//迭代器
Iterator<Student> it = c.iterator();
//遍历
while(it.hasNext()){
Student s = (Student)(it.next());
System.out.println(s.getName() + "---" + s.getAge());
}
}
- 注:使用迭代器获取next()下一个元素的时候,一定看清楚集合存储的元素是什么类型,否则会出现ClassCaseException------>类型转换异常;
4. List接口与实现类
4.1 List接口概述
有序的 collection,此接口的用户可以对列表中每个元素的插入位置进行精确地控制。 用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。
有序集合,改接口可精确控制每个元素的插入位置。通过整数索引访问元素,搜索列表中的元素。
特点:
有序、有下标、元素可重复。
继承了父接口提供的共性方法,同时定义了一些独有的与下标相关的操作方法。
4.1.1 存储字符串并遍历案例
public static void main(String[] args) {
//创建一个List集合对象
List<String> list = new ArrayList<String>();
//添加元素
list.add("kaka");
list.add("hello");
list.add("world");
list.add("java");
list.add("kaka");
//使用Collection的迭代器
Iterator<String> it = list.iterator();
//遍历
while(it.hasNext()){
String s = (String)(it.next());
System.out.println(s + "---" + s.length());
}
}
4.2 List的集合特有功能
- void add(int index,Object element):在指定的位置处添加元素
- Object remove(int index):删除指定索引处的元素
- Object get(int index):获取功能: 获取指定索引处的元素
- Object set(int index,E element):在指定位置处,修改元素内容
- ListIterator listIterator(): list集合的专有遍历方式:列表迭代器
public static void main(String[] args) {
//创建List集合对象
List<String> list = new ArrayList<String>();
//添加元素
list.add("kaka");
list.add("hello");
list.add("world");
list.add("java");
//在指定的位置处添加元素
list.add(2, "python");
//删除指定索引处的元素
System.out.println(list.remove(2));//python
//获取指定索引处的元素
System.out.println(list.get(0));//kaka
//在指定位置处修改元素内容
System.out.println(list.set(0, "卡卡"));//kaka
System.out.println("list:" +list);//[卡卡, hello, world, java]
}
4.2.1 get(int index)+size()相结合遍历案例_03
需求:有5个学生,都有姓名和年龄,现需要将5个学生存储到集合中,并遍历5个学生信息
1)定义一个学生类
2)创建集合对象 List
3)创建5个学生
5)将5个学生添加到集合中
6)get(int index)+size()相结合遍历
//学生类
public class Student {
private String name ;
private int age ;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
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 + "]";
}
}
//创建一个List集合对象
List<Student> list1 = new ArrayList<Student>();
//创建5个学生对象
Student s1 = new Student("卡卡",23);
Student s2 = new Student("张三",23);
Student s3 = new Student("李四",23);
Student s4 = new Student("王五",23);
Student s5 = new Student("赵六",23);
//get(int index)+size()相结合 普通for循环
for(int x = 0 ; x < list.size() ; x ++) {
Student s =(Student)(list1.get(x)) ;
System.out.println(s.getName()+"---"+s.getAge());
}
}
4.3 列表迭代器_ ListIterator
ListIterator listIterator(): list集合的专有遍历方式:列表迭代器;
ListIterator:接口
正向遍历
boolean hasNext() :判断是否有下一个可以迭代的元素
Object next() :获取下一个元素
逆向遍历
boolean hasPrevious() :判断是否有上一个可以迭代的元素
Object previous() :获取上一个元素
public static void main(String[] args) {
//创建一个List集合
List<String> list = new ArrayList<String>();
//添加字符串元素
list.add("kaka");
list.add("hello");
list.add("java");
//获取列表迭代器
ListIterator<String> lit = list.listIterator();
//遍历
while(lit.hasNext()) {
String s = (String)(lit.next()) ;
System.out.println(s);
}
System.out.println("--------------------");
//逆向遍历
while(lit.hasPrevious()) {
String s = (String)(lit.previous()) ;
System.out.println(s);
}
}
4.3.1 使用迭代器遍历的问题
如果使用迭代器遍历元素,就不能使用集合添加元素;
java.util.ConcurrentModificationException:并发修改异常 ;
4.3.1.1 使用迭代器遍历,迭代器添加元素
public static void main(String[] args) {
//创建一个List集合对象
List<String> list = new ArrayList<String>();
//集合存储三个元素
list.add("hello") ;
list.add("world") ;
list.add("java") ;
//由于Collection的Iterator迭代器没有添加功能的,所以列表迭代器
ListIterator<String> lit = list.listIterator() ;
while(lit.hasNext()) {
String s = (String)(lit.next()) ;
//判断
if("world".equals(s)) {
//迭代器添加元素
lit.add("javaee");
}
}
System.out.println("list:"+list);
4.3.1.2 使用集合遍历,集合添加元素
public static void main(String[] args) {
//创建一个List集合对象
List<String> list = new ArrayList<String>();
//集合存储三个元素
list.add("hello") ;
list.add("world") ;
list.add("java") ;
//普通for循环:get(int index) 和 size()方法先结合
for(int i = 0 ;i < list.size() ; i ++) {
//获取元素
String s = (String)(list.get(i)) ;
//判断
if("world".equals(s)) {
//使用集合添加
list.add("javaee") ;
}
}
System.out.println("list:"+list);
}
4.4 集合的四种遍历方式案例
public static void main(String[] args) {
//创建ArrayList集合对象
ArrayList<String> array = new ArrayList<String>() ;
//给集合中添加元素
array.add("kaka") ;
array.add("hello") ;
array.add("world") ;
array.add("world") ;
array.add("java") ;
array.add("java") ;
//1:Object[] toArray遍历
Object[] objs = array.toArray() ;
for(int x = 0 ; x < objs.length ; x ++) {
String s = (String)(objs[x]) ;
System.out.println(s+"---"+s.length());
}
System.out.println("-----------------------");
//2:Collection的迭代器
Iterator<String> it = array.iterator() ;
while(it.hasNext()) {
String s = (String)(it.next()) ;
System.out.println(s+"---"+s.length());
}
System.out.println("-----------------------");
//3:使用List集合的列表迭代器
ListIterator<String> lit = array.listIterator() ;
while(lit.hasNext()) {
String s = (String)(lit.next()) ;
System.out.println(s+"---"+s.length());
}
System.out.println("-----------------------");
//4:Object get(int index) 和int size()方法相集合
for (int i = 0; i < array.size(); i++) {
String s = (String)(array.get(i)) ;
System.out.println(s+"---"+s.length());
}
}
4.5 List集合的三个子实现类的特点
ArrayList:
底层数据结构:数组----->查询快,增删慢
从线程角度考虑:此实现不是同步的---->线程不安全---->执行效率高!
LinkedList:
底层数据结构:链接列表(链表)---->查询慢,增删快
从线程角度考虑:此实现不是同步的----->线程不安全---->执行效率高!
Vector:
底层数据库结构:可增长的数组实现---->查询快.增删慢
线程方面: 线程安全--->同步----->执行效率低!
除多线程环境外,在需求中没有指定具体的集合---->都使用ArrayList ()
4.6 ArrayList集合
见4.4,4.5;
4.6.1 存储自定义对象并遍历
需求:有5个学生,都有姓名和年龄,现需要将5个学生存储到集合中,并遍历5个学生信息
1)定义一个学生类
2)创建集合对象 ArrayList
3)创建5个学生
5)将5个学生添加到集合中
6)创建迭代器
7)利用迭代器遍历集合
//学生类
public class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
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 static void main(String[] args) {
//创建ArrayList集合对象
ArrayList<Student> array = new ArrayList<Student>();
//创建5个学生对象
Student s1 = new Student("卡卡",23);
Student s2 = new Student("张三",23);
Student s3 = new Student("李四",23);
Student s4 = new Student("王五",23);
Student s5 = new Student("赵六",23);
//集合中添加元素
array.add(s1);
array.add(s2);
array.add(s3);
array.add(s4);
array.add(s5);
//迭代器
Iterator<Student> it = array.iterator();
//遍历
while(it.hasNext()){
Student s = (Student)(it.next());
System.out.println(s.getName() + "---" + s.getAge());
}
}
4.6.2 案例:获取10个1-20之间的随机数,要求不能重复,使用ArrayList集合
public static void main(String[] args) {
ArrayLists();
}
private static void ArrayLists() {
ArrayList<Integer> arr = new ArrayList<>();
Random r = new Random();
while(arr.size() != 10){
int number = r.nextInt(20)+1 ;
if(!arr.contains(number)){
arr.add(number) ;
}
}
System.out.println("ArrayList版本:");
//遍历
Iterator<Integer> it = arr.iterator();
while(it.hasNext()){
Integer i = (Integer)(it.next());
System.out.print(i + "\t");
}
}
4.7 Vector集合
见4.5
通过整数索引访问组件;
线程安全的类:StringBuffer 和 Vector
Vector类特有功能:
public void addElement(Object obj):给Vector集合中添加元素 ------->类似于add(Object obj)
public Object elementAt(int index):通过整数索引值获取指定元素内容---->类似于Object get(int index)
public Enumeration elements() :就是Vector集合的专有遍历方式:返回Enumeration接口(枚举元素)----->类似于:Iterator iterator()
Enumeration接口:
- boolean hasMoreElements():判断枚举中是否存在元素
- Object nextElement():获取下一个枚举元素
public static void main(String[] args) {
//创建Vector集合对象
Vector<String> v = new Vector<String>();
//给Vector集合中添加元素
v.add("kaka");
v.add("hello");
v.add("world");
v.add("java");
//通过整数索引值获取指定元素内容 + size()遍历Vector集合
for(int i = 0; i < v.size(); i++){
String s = (String)(v.elementAt(i));
System.out.println(s + "---" + s.length());
}
System.out.println("------------");
//特有遍历
Enumeration<String> em = v.elements();
while(em.hasMoreElements()){
String s = (String)(em.nextElement());
System.out.println(s + "---" + s.length());
}
}
4.8 ListedList集合
见4.5
ListedList集合特有功能:
添加
public void addFirst(Object e):将指定元素始终在链表开头添加
public void addLast(Object e):将指定的元素在链表的末尾添加
获取
public Object getFirst() :获取链表的第一个元素
public Object getLast() :获取链表的最后一个元素
删除
public Object removeFirst():删除链表第一个元素
public Object removeLast() :删除链表最后一个元素
public static void main(String[] args) {
//创建一个LinkeList集合对象
LinkedList<String> link = new LinkedList<String>() ;
link.add("hello") ;
link.add("world") ;
link.add("java") ;
//将指定元素始终在链表开头添加
link.addFirst("javaee");
link.addFirst("android");
//将指定的元素在链表的末尾添加
link.addLast("go");
link.addLast("R");
//获取链表的第一个元素,返回被获取的元素
System.out.println("getFirst():"+link.getFirst());//android
//获取链表的最后一个元素
System.out.println("getLast():"+link.getLast());//R
//删除链表第一个元素
System.out.println("removeFirst():"+link.removeFirst());//android
//删除链表最后一个元素
System.out.println("removeLast():"+link.removeLast());//R
System.out.println("link:"+link);//[javaee, hello, world, java, go]
}
4.8.1 利用ListedList 集合模拟栈结构特点_01
栈的特点:先进后出;
利用ListedList 中的 public void addFirst(Object e)方法,将指定元素始终在链表开头添加,实现模拟栈的结构特点;
public static void main(String[] args) {
//创建一个LinkedList集合
LinkedList<String> link = new LinkedList<String>() ;
//addFirst()添加
link.addFirst("kaka");
link.addFirst("hello");
link.addFirst("java");
//遍历
//使用迭代器
Iterator<String> it = link.iterator();
while(it.hasNext()) {
String s = (String)(it.next()) ;
System.out.println(s);
}
}
4.8.2 利用ListedList 集合模拟栈结构特点_02
利用ListedList 中的 public void addFirst(Object e)方法,将指定元素始终在链表开头添加,在利用public Object removeFirst()方法,删除链表第一个元素;一加一删来实现模拟栈结构特点;
import java.util.LinkedList;
/**
* 自定义的栈集合类
* @author 卡卡
*
*/
public class MyStack {
private LinkedList link;
//定义无参构造
public MyStack(){
link = new LinkedList();
}
/**
* 添加
*/
public void add(Object obj){
link.addFirst(obj);
}
/**
* 获取
*/
public Object get(){
return link.removeFirst();
}
/**
* 判断
*/
public boolean isEmpy(){
return link.isEmpty();
}
}
/*
* 测试类
*/
public class MyStackTest {
public static void main(String[] args) {
//创建MyStack对象
MyStack my = new MyStack();
//添加元素
my.add("kaka");
my.add("hello");
my.add("world");
while(!my.isEmpy()){
//获取元素
System.out.println(my.get());
}
}
}
4.9 List 案例_01
需求:在ArrayList存储了一些重复元素,去重ArrayList重复的元素!(字符串元素)
创建一个新集合的思想
- 创建一个ArrayList集合对象 array
- 给集合中添加很多重复元素
- 创建一个新的集合newArray
- 遍历以前的集合
- 判断新集合如果不包含这个元素,就将这个元素添加到新集合中
- 遍历新集合
public static void main(String[] args) {
//创建一个ArrayList集合
ArrayList<String> arr = new ArrayList<>();
//给集合中添加重复元素
arr.add("kaka");
arr.add("hello");
arr.add("world");
arr.add("java");
arr.add("kaka");
arr.add("hello");
arr.add("kaka");
arr.add("java");
//创建一个新集合
ArrayList<String> newArr = new ArrayList<>();
//遍历以前的元素
Iterator<String> it = arr.iterator();
while(it.hasNext()){
//获取元素
String s = (String)(it.next());
//判断新集合如果不包含这个元素,添加到新集合中;
if(! newArr.contains(s)){
newArr.add(s);
}
}
//遍历新集合
Iterator<String> itN = newArr.iterator();
while(itN.hasNext()){
String s = (String)(itN.next());
System.out.println(s);
}
}
4.10 List案例_02
需求:在ArrayList存储了一些重复元素,去重ArrayList重复的元素!(字符串元素)
不创建新集合,利用选择排序的思想
- 使用0索引对应的元素和后面索引的元素进行比较,如果后面的元素和前面元素一致,就将后面重复元素从集合删除掉----->remove(int index)
- 创建ArrayList集合对象
- 添加重复元素
- 利用选择排序的思想,删除重复的元素
- 遍历集合
public static void main(String[] args) {
//创建一个ArrayList集合
ArrayList<String> arr = new ArrayList<>();
//给集合中添加重复元素
arr.add("kaka");
arr.add("hello");
arr.add("world");
arr.add("java");
arr.add("kaka");
arr.add("hello");
arr.add("kaka");
arr.add("java");
//利用选择排序的思想,将后面重复元素从集合删除掉
for(int i = 0 ;i < arr.size()-1 ;i ++) {
for(int j = i+1 ; j < arr.size(); j++) {
//如果后面元素和前面的元素重复了,删除后面元素,里面索引--
//通过角标获取集合元素内容get(int index)
if(arr.get(i).equals(arr.get(j))) {
//删除
arr.remove(j) ;
j -- ;
}
}
}
//遍历集合
Iterator<String> it = arr.iterator() ;
while(it.hasNext()) {
String s = (String)(it.next()) ;
System.out.println(s);
}
}
4.11 List案例_03
需求:使用ArrayList集合存储自定义对象Student并去重
1)定义一个学生类
2)创建集合对象 ArrayList
3)创建5个学生
5)将5个学生添加到集合中
6)创建迭代器
7)利用迭代器遍历集合
重点:重写equals方法
//学生类
public class Student {
private String name ;
private int age ;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
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 boolean equals(Object obj) {
//Student s ;
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())//获取字节码文件对象: this.getClass
return false;
Student other = (Student) obj;
if (age != other.age) //比较当前学生类中成员信息
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name)) //String name
return false;
return true;
}
}
public static void main(String[] args) {
//创建ArrayList集合对象
ArrayList<Student> arr = new ArrayList<>();
//创建学生对象
//创建对象
Student s1 = new Student("卡卡",23);
Student s2 = new Student("张三",23);
Student s3 = new Student("李四",23);
Student s4 = new Student("卡卡",23);
Student s5 = new Student("王五",23);
Student s6 = new Student("赵六",23);
//添加到集合中
arr.add(s1);
arr.add(s2);
arr.add(s3);
arr.add(s4);
arr.add(s5);
arr.add(s6);
//创建一个新集合
ArrayList<Student> newArr = new ArrayList<>();
//遍历以前的集合
Iterator it = arr.iterator();
while(it.hasNext()){
Student s = (Student)(it.next());
if(!newArr.contains(s)){
newArr.add(s);
}
}
//遍历新的集合
Iterator<Student> it2 = newArr.iterator();
for(int i = 0; i < newArr.size();i++){
Student s = (Student)(newArr.get(i));
System.out.println(s.getName() + "---" +s.getAge());
}
}
5. Set集合与实现类
5.1 Set 概述
Set接口就是一个不包含重复元素的collection;全部继承自Collection中的方法;
特点:
无序、无下标、元素不可以重复
Set集合和List集合的区别:
- List集合:有序的集合,存储和取出是一致的,它允许元素重复
- Set集合:无序的集合,存储和取出不一致(不能保证该顺序恒久不变),它元素唯一的
public static void main(String[] args) {
//创建一个Set集合对象
Set<String> set = new HashSet<String>();
//添加元素
set.add("hello");
set.add("hello");
set.add("java");
set.add("java");
set.add("world");
set.add("world");
//增强for遍历
for(String s :set){
System.out.println(s);//java world hello
}
}
- 元素不能重复
5.2 Set集合中的子实现类
Set中的子实类包括HashSet、LinkedHashSet、TreeSet
5.2.1 HashSet类概述
HashSet集合的add方法跟HashMap集合的put有关系,将所有需要存入HashSet的值,直接保存在HashMap中,底层依赖于hashCode()、equals()方法。需要在自定义的类中重写hashCode()和equals方法();
需求:使用HashSet集合存储自定义对象Student,保证元素唯一
//学生类
public class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
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 int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
//result = 31 * 29 + name的哈希值
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
public static void main(String[] args) {
//创建一个HashSet集合对象
Set<Student> set = new HashSet<Student>();
//创建学生对象
Student s1 = new Student("卡卡",23);
Student s2 = new Student("张三",26);
Student s3 = new Student("卡卡",24);
Student s4 = new Student("张三",26);
Student s5 = new Student("卡卡",34);
//添加集合中
set.add(s1);
set.add(s2);
set.add(s3);
set.add(s4);
set.add(s5);
//增强for遍历
for(Student s : set){
System.out.println(s.getName()+"---"+s.getAge());
}
}
以上代码输出:
卡卡---23
卡卡---24
卡卡---34
张三---26
5.2.2 LinkedHashSet类概述
元素有序唯一,底层数据结构是链接列表和哈希表
- 链接列表: 来保证元素有序(存储和取出一致的)
- 哈希表: 来保证元素唯一性
节点形式单独存储数据,并可以指向下一个节点,通过顺序访问节点,可保留元素插入顺序;
public static void main(String[] args) {
//创建LinkedHashSet集合对象
LinkedHashSet<String> link = new LinkedHashSet<String>();
//添加元素
link.add("hello");
link.add("hello");
link.add("kaka");
link.add("kaka");
link.add("javaEE");
link.add("javaEE");
link.add("android");
//遍历
for(String s : link){
System.out.println(s);
}
}
以上代码输出:
hello
kaka
javaEE
android
6 TreeSet 类概述(重)
底层数据结构是红黑树一种自平衡的二叉树;
1). 实现了SortedSet接口,要求必须可以对元素排序,使用元素的自然顺序对元素进行排序。
2). 所有插入元素,必须实现Comparable接口,覆盖compareTo方法。
3). 根据compareTo方法返回0作为去重的依据
6.1 Red - Black - Tree 红黑树结构简述
红黑树一种自平衡的二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。
public static void main(String[] args) {
//创建TreeSet集合对象
TreeSet<Integer> ts = new TreeSet<Integer>();
//add()添加
ts.add(20) ;
ts.add(18) ;
ts.add(23) ;
ts.add(22) ;
ts.add(17) ;
ts.add(24) ;
ts.add(19) ;
ts.add(18) ;
ts.add(24) ;
//遍历集合
for(Integer i : ts) {
System.out.print(i+" ");//17 18 19 20 22 23 24
}
}
遍历原理:拿上面的数字20,18,23,22,17,24,19,18,24来说:
存储元素:
- 添加元素时,第一个元素20作为根节点---->root
- 后面添加的元素都需要和根节点进行比较
- 如果比根节点小,作为根节点的左孩子(根节点左边的子节点)
- 如果比根节点打,作为根节点的右孩子(根节点右边的子节点)
- 如果元素相等,不会进入到红黑树的结构中
遍历元素:
使用中序遍历(左根右)
- 首先访问根节点的左孩子,如果这个左孩子仍然有左孩子继续访问,一直到没有左孩子的节点,输出该节点17;
- 依据中序遍历次序,输出17的父节点18,;
- 在输出18的右孩子19;
- 以节点18为大的左孩子输出完毕,在输出整个二叉树的根节点20;
- 依据中序遍历次序左根右,找到根节点20的右孩子23,因为23有左孩子所以输出23的左孩子22;
- 输出22的根节点23;
- 在输出23的右孩子24;
- 最终得到序列17,18,19,20,22,23,24
6.2 TreeSet 集合案例_按照学生的年龄从小到大排序
TreeSet集合存储自定义对象,并且主要条件按照学生年龄的长度(从小到大比较)
主要条件:年龄从小到大排序
次要条件:
长度如果一样,还需要比较姓名的内容
需要比较人的年龄是否一样
/*
* 如果要使用自然排序,针对自定义,该自定义类必须实现Comparable接口
* 重写 compareTo(T s)方法对元素进行比较
*/
public class Student implements Comparable<Student>{
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
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) {
// TODO Auto-generated method stub
int num = this.age - s.age;
int num2 = (num == 0?(this.name.compareTo(s.name)):num);
return num2;
}
}
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>();
Student s1 = new Student("kaka",23);
Student s2 = new Student("kaka",21);
Student s3 = new Student("kaaka",28);
Student s4 = new Student("kkkkaka",26);
Student s5 = new Student("ka11ka",24);
Student s6 = new Student("kakaaa",23);
Student s7 = new Student("kaka",23);
//添加元素
ts.add(s1);
ts.add(s2);
ts.add(s3);
ts.add(s4);
ts.add(s5);
ts.add(s6);
ts.add(s7);
//遍历
for(Student s : ts){
System.out.println(s.getName()+"---"+s.getAge());
}
}
以上代码输出:
kaka---21
kaka---23
kakaaa---23
ka11ka---24
kkkkaka---26
kaaka---28
6.3 TreeSet 集合案例_按照学生的
姓名长度从小到大排序
/*
* 学生类
*/
public class Student implements Comparable<Student> {
private String name ;
private int age ;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
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 + "]";
}
//重写Comparable接口的方法
@Override
public int compareTo(Student s) {
//主要条件按照学生姓名的长度(从小到大)
int num = this.name.length() - s.name.length() ;
//1)次要条件:姓名的长度一样,姓名的内容不一定一样
int num2 = num == 0 ? (this.name.compareTo(s.name)) : num;
//2)次要条件:姓名的长度一样,内容一样,年龄不一定一样
int num3 = num2 == 0 ? (this.age-s.age) : num2 ;
return num3 ;
}
}
public static void main(String[] args) {
//创建一个TreeSet集合 对象
TreeSet<Student> ts = new TreeSet<Student>() ; //实现自然排序
//创建学生对象
Student s1 = new Student("kaka",23);
Student s2 = new Student("kaka",21);
Student s3 = new Student("kaaka",28);
Student s4 = new Student("kkkkaka",26);
Student s5 = new Student("ka11ka",24);
Student s6 = new Student("kakaaa",23);
Student s7 = new Student("kaka",23);
ts.add(s1) ;
ts.add(s2) ;
ts.add(s3) ;
ts.add(s4) ;
ts.add(s5) ;
ts.add(s6) ;
ts.add(s7) ;
//增强for
for(Student s :ts) {
System.out.println(s.getName()+"---"+s.getAge());
}
}
以上代码输出:
kaka---21
kaka---23
kaaka---28
ka11ka---24
kakaaa---23
kkkkaka---26
6.4 TreeSet集合两种比较器排序
构造方法:
TreeSet():创建TreeSet集合对象使用自然排序
TreeSet(Comparator comparatpr):比较器排序
构造方法的形式参数是一个接口类型:
自定义类实现Comarator接口,重写compare(T o1 ,T o2)方法
接口的匿名内部类
new 接口名(){
重写接口中的方法;
};
注:6.4.1和6.4.2学生类都是以下
/*
* 学生类
*/
public class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
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 + "]";
}
}
6.4.1 自定义类实现Comparator接口
/*
* Comparator接口
*/
public class MyComparator implements Comparator<Student>{
public MyComparator() {
}
@Override
public int compare(Student s1, Student s2) {
//s1----->this
//s2---->传进来被比较的对象
//主要条件:按照学生年龄从小到大
int num = s1.getAge() - s2.getAge() ;
//次要条件:如果年龄一样,比较姓名的内容是否一样
int num2 = num == 0 ? (s1.getName().compareTo(s2.getName())) : num ;
return num2;
}
}
public static void main(String[] args) {
//创建一个TreeSet集合对象
//TreeSet(Comparator comparatpr):比较器排序
TreeSet<Student> ts = new TreeSet<Student>(new MyComparator()) ;
//创建几个学生对象
Student s1 = new Student("kaka",23);
Student s2 = new Student("kaka",21);
Student s3 = new Student("kaaka",28);
Student s4 = new Student("kkkkaka",26);
Student s5 = new Student("ka11ka",24);
Student s6 = new Student("kakaaa",23);
Student s7 = new Student("kaka",23);
//添加元素
ts.add(s1) ;
ts.add(s2) ;
ts.add(s3) ;
ts.add(s4) ;
ts.add(s5) ;
ts.add(s6) ;
ts.add(s7) ;
//遍历
for(Student s: ts) {
System.out.println(s.getName()+"---"+s.getAge());
}
}
以上代码输出:
kaka---21
kaka---23
kakaaa---23
ka11ka---24
kkkkaka---26
kaaka---28
6.4.2 直接接口的匿名内部类
public static void main(String[] args) {
//直接接口的匿名内部类
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student s1, Student s2) {
//s1----->this
//s2---->传进来被比较的对象
//主要条件:按照学生年龄从小到大
int num = s1.getAge() - s2.getAge() ;
//次要条件:如果年龄一样,比较姓名的内容是否一样
int num2 = num == 0 ? (s1.getName().compareTo(s2.getName())) : num ;
return num2;
}
});
//创建几个学生对象
Student s1 = new Student("kaka",23);
Student s2 = new Student("kaka",21);
Student s3 = new Student("kaaka",28);
Student s4 = new Student("kkkkaka",26);
Student s5 = new Student("ka11ka",24);
Student s6 = new Student("kakaaa",23);
Student s7 = new Student("kaka",23);
//添加元素
ts.add(s1) ;
ts.add(s2) ;
ts.add(s3) ;
ts.add(s4) ;
ts.add(s5) ;
ts.add(s6) ;
ts.add(s7) ;
//遍历
for(Student s: ts) {
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
以上代码输出:
kaka---21
kaka---23
kakaaa---23
ka11ka---24
kkkkaka---26
kaaka---28
7. Map接口与实现类
7.1 Map接口的概述
Map集合数据结构 键值对存储一对数据;
Map接口的特点:
- 用于存储任意类型的键值对(Key-value)
- 键:无序、无下标、不允许重复(唯一)
- 值:无序、无下标、允许重复
- 针对键有效,跟值无关
Map接口和Collection接口的不同:
- Map是双列的,存储一堆键值对元素,特点针对键有效,键是唯一的可理解为(夫妻对),数据结构值针对键有效跟值无关;
- Collection是单列的 ,只能存储一种引用数据类型,子体系Set是唯一的,理解为光棍,数据结构是针对元素有效;
7.2 Map集合的基本功能
- V put(K key,V value) :添加一个键值对元素(后面的值会将前面的值覆盖,存储到集合,返回第一次存储的键对应的值)
- V remove(Object key) :删除键,返回键对应的值
- void clear() :暴力删除(删除全部键值对元素)
- boolean containsKey(Object key):判断是否包含指定的键
- boolean containsValue(Object value):判断是否包含指定的值
- boolean isEmpty() :判断Map集合是否为空
- int size() :获取集合的元素数
public static void main(String[] args) {
//创建Map集合对象
Map<String,String> map = new HashMap<String,String>();
//添加一个键值对元素
//后面的值会将前面的值覆盖,存储到集合,返回第一次存储的键对应的值
//第一次添加返回null
System.out.println(map.put("卡卡", "涛涛"));//null
System.out.println(map.put("卡卡", "牛牛"));//涛涛
System.out.println(map);//{卡卡=牛牛}
//删除键,返回键对应的值
System.out.println("remove():"+map.remove("杨过"));
//暴力清除
map.clear();
//判断是否包含指定的键
System.out.println("containsKey():"+map.containsKey("卡卡"));//true
System.out.println("containsKey():"+map.containsKey("唐唐"));//false
//判断是否包含指定的值
System.out.println("containsValue():"+map.containsValue("牛牛"));//true
//判断Map集合是否为空
System.out.println("isEmpty():"+map.isEmpty());//false
//获取集合的元素数
System.out.println(map.size());//1
System.out.println(map);//{卡卡=牛牛}
}
7.3 Map接口中的其他功能
- V get(Object key):通过键获取值
- Set < K> keySet() :获取所有的键的集合
- Collection< V> values():获取所有的值的集合
- Set> entrySet() :获取的是键值对对象(用于遍历详见7.4.2)
public static void main(String[] args) {
//创建Map集合
Map<String,String> map = new HashMap<String,String>() ;
//添加元素
map.put("卡卡", "小卡") ;
map.put("牛牛", "小牛") ;
map.put("堂堂", "小堂") ;
map.put("涛涛", "小涛") ;
// 获取所有的键的集合
Set<String> set = map.keySet() ;
//增强for
for(String key : set) {
//通过键获取值
String value = map.get(key) ;
System.out.println(key+"="+value);
}
System.out.println("-----------------------");
//获取所有的值的集合
Collection<String> c = map.values() ;
for(String value : c) {
System.out.println(value);
}
}
上述代码输出:
卡卡=小卡
堂堂=小堂
涛涛=小涛
牛牛=小牛小卡
小堂
小涛
小牛
7.4 Map集合的遍历
7.4.1 通过键找值
set< K > keySet() {}
- 获取所有键的集合
- 遍历键的集合,获取到每一个键
- 根据键找值
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("卡卡", "小卡") ;
map.put("牛牛", "小牛") ;
map.put("堂堂", "小堂") ;
map.put("涛涛", "小涛") ;
//获取所有的键的集合
Set<String> set = map.keySet() ;
for(String key :set) {
//通过键获取值 V get(Object key)
String value = map.get(key) ;
System.out.println(key+"="+value);
}
}
7.4.2 根据键值对对象找键和值
public Set> entrySet()
- Map.Entry接口中
- K getKey():获取键
- V getValue():获取值
- 获取所有键值对对象的集合
- 遍历键值对对象的集合,获取到每一个键值对对象
- 根据键值对对象找键和值
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>() ; //HashMap:哈希表(元素唯一,无序!)
//添加元素
map.put("卡卡", "小卡") ;
map.put("牛牛", "小牛") ;
map.put("堂堂", "小堂") ;
map.put("涛涛", "小涛") ;
//通过map集合获取所有的键值对对象
Set<Map.Entry<String, String>> entrySet = map.entrySet() ;
for(Map.Entry<String, String> entry:entrySet ) {
//通过entry所有的键值对对象
String key = entry.getKey() ;
String value = entry.getValue() ;
System.out.println(key+"="+value);
}
}
7.5 HashMap 集合类
键是哈希表结构,可以保证键的唯一性;可以用null作为key或者value;
HashMap:可以存储任意的引用类型数据;
- HashMap< String ,String>
- HashMap < String ,Integer>
- HashMap < String ,Student>
7.5.1 相同类型
public static void main(String[] args) {
//创建一个HashMap集合
HashMap<String, String> map = new HashMap<String,String>() ;
//添加元素
map.put("卡卡", "小卡") ;
map.put("牛牛", "小牛") ;
map.put("堂堂", "小堂") ;
map.put("涛涛", "小涛") ;
//直接遍历
Set<String> set = map.keySet() ;
for(String key :set) {
String value = map.get(key) ;
System.out.println(key+"---"+value);
}
}
7.5.2 不同类型
public static void main(String[] args) {
//创建HashMap集合
HashMap<String, Student> hm = new HashMap<String,Student>() ;
hm.put("1001", new Student("卡卡",27)) ;
hm.put("1002", new Student("牛牛",25)) ;
hm.put("1003", new Student("堂堂",22)) ;
hm.put("1004", new Student("涛涛",20)) ;
hm.put("1005", new Student("丫丫",18)) ;
//遍历集合
Set<String> set = hm.keySet() ;
for(String key :set ) {
//通过键获取值
Student s = hm.get(key) ;
System.out.println(key+"---"+s.getName()+"---"+s.getAge());
}
}
7.5.3 自定义类型
如果HashMap键的类型是自定义的,必须重写hashCode()和equals方法()保证元素唯一;
- String:学号
- Key:Student类型:学生信息
/*
* 自定义学生类
*/
public class Student {
private String name ;
private int age ;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", 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 int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public static void main(String[] args) {
//创建一个HashMap集合
HashMap<Student, String> hm = new HashMap<Student,String>() ;
Student s1 = new Student("卡卡", 29) ;
Student s2 = new Student("卡卡", 25) ;
Student s3 = new Student("卡卡", 29) ;
Student s4 = new Student("涛涛", 30) ;
Student s5 = new Student("涛涛", 31) ;
Student s6 = new Student("帆帆", 22) ;
//添加元素
hm.put(s1, "1001") ;
hm.put(s2, "1002") ;
hm.put(s3, "1003") ;
hm.put(s4, "1004") ;
hm.put(s5, "1005") ;
hm.put(s6, "1006") ;
Set<Student> set = hm.keySet() ;
for(Student key :set) {
String value = hm.get(key) ;
System.out.println(key.getName()+"---"+key.getAge()+"---"+value);
}
}
7.6 Map案例
需求:键盘录入,获取字符串中每一个字母出现的次数
步骤:
- 创建键盘录入对象,录入字符串内容
- 创建Map集合,TreeMap
- 将字符串转换成字符数组
- 遍历字符数组,获取到每一个字符
- 利用Map集合对象通过键获取值 ,判断当前获取的值是否null
- 如果为null,第一次添加,给值默认值1,map集合对象将键和值添加到集合
- 如果不为null,说明键不是第一次添加,值自增,重写map集合键和值添加到集合中
- 创建字符串缓冲区对象StringBuilder
- 遍历TreeMap
- 使用字符串缓冲区对象将键和值拼接起来,转换成字符串
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("输入内容:");
String line = sc.next();
//创建Map集合
TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
//字符串转化为数组
char[] chs = line.toCharArray();
//遍历数组
for(char ch :chs){
//通过键获取值
Integer i = tm.get(ch);
//判断是否为null
if(i == null){
tm.put(ch, 1);
}else{
i++;
tm.put(ch, i);
}
}
//创建字符串缓冲区对象
StringBuilder sb = new StringBuilder();
Set<Character> set = tm.keySet();//Map存到Set
for(Character key :set){
//获取值
Integer value = tm.get(key);
//拼接
sb.append(key).append("(").append(value).append(")");
}
String result = sb.toString();
System.out.println(result);
}
}
7.7 集合的嵌套遍历 _01
ArrayList集合嵌套HashMap集合 ArrayList>
public static void main(String[] args) {
//创建一个大集合
ArrayList<HashMap<String,String>> array = new ArrayList<HashMap<String,String>>();
//第一个子集合HashMap<String,String>
HashMap<String,String> hm1 = new HashMap<String,String>();
//添加元素
hm1.put("卡卡", "小卡");
hm1.put("牛牛", "小牛");
//将第一个集合添加到大集合中
array.add(hm1);
//第二个子集合
HashMap<String,String> hm2 = new HashMap<String,String>();
//添加元素
hm2.put("欧欧", "小欧");
hm2.put("QQ", "小Q");
array.add(hm2);
//第三个子集合
HashMap<String,String> hm3 = new HashMap<String,String>();
//添加元素
hm3.put("发发", "小发");
hm3.put("安安", "小安");
array.add(hm3);
for(HashMap<String,String> map : array){
//获取所有键的集合
Set<String> set = map.keySet();
for(String key : set){
//键找值
String value = map.get(key);
System.out.println("\t" + key +"---" +value);
}
}
}
7.8 集合的嵌套遍历 _02
HashMap集合嵌套ArrayList集合HashMap>
- 键:String
- 值:HashMap
public static void main(String[] args) {
//创建一个大集合
HashMap<String,ArrayList<String>> hm = new HashMap<String,ArrayList<String>>();
//Key:String类型
//value:ArrayList集合
ArrayList<String> firstArray = new ArrayList<String>();
firstArray.add("刘备");
firstArray.add("曹操");
//将子集合添加到大集合中
hm.put("三国演义", firstArray);
ArrayList<String> secArray = new ArrayList<String>();
secArray.add("令狐冲");
secArray.add("林平之");
//将子集合添加到大集合中
hm.put("笑傲江湖", secArray);
ArrayList<String> thirArray = new ArrayList<String>();
thirArray.add("宋江");
thirArray.add("吴用");
//将子集合添加到大集合中
hm.put("水浒传", thirArray);
//遍历
//获取所有集合
Set<String> set = hm.keySet();
//遍历键
for(String key : set){
System.out.println(key);
//通过键获取值
ArrayList<String> list = hm.get(key);
//遍历ArrayList
for(String value : list){
System.out.println("\t" + value);
}
}
}
8. Collections工具类
集合工具类,针对集合操作的工具类,定义了除了存取以外的集合常用方法。
8.1 Collection 的成员方法
- public static void sort(List list):针对集合进行默认的自然排序
- public static < T > void sort(List< T > list, Comparator<? super T> c):针对List集合的比较器排序
- public static int binarySearch(List<?> list,T key):集合中查询指定的元素出现的索引值(二分搜索法)
- public static T max(Collection<?> coll):获取集合中的最大值
- public static void reverse(List<?> list):直接集合的数据进行反转
- public static void shuffle(List<?> list):针对集合中元素随机置换
注:折半查找(二分搜索法)---->数组中的元素必须有序的 ,数组的元素是无序的,就不能够直接使用二分搜索法
public static void main(String[] args) {
//创建List集合对象
List<Integer> list = new ArrayList<Integer>();
//添加元素
list.add(50);
list.add(30);
list.add(79);
list.add(10);
list.add(49);
System.out.println(list);//[50, 30, 79, 10, 49]
//针对集合进行默认的自然排序
Collections.sort(list);
System.out.println(list);//[10, 30, 49, 50, 79]
//集合中查询指定的元素出现的索引值(二分搜索法)
System.out.println("index:" + Collections.binarySearch(list, 30));//index:1
//获取集合中的最大值
System.out.println("max:" + Collections.max(list));//max:79
//集合的数据进行反转
Collections.reverse(list);
System.out.println(list);//[79, 50, 49, 30, 10]
//针对集合中元素随机置换
Collections.shuffle(list);
System.out.println(list);//[30, 50, 79, 10, 49]每次不定是随机生成的
}
8.2 针对List集合的比较器排序
public static < T > void sort(List< T > list, Comparator<? super T> c):针对List集合的比较器排序
需求:List集合中存储的是Student类型,按照学生的年龄从小到大排序,,排序的过程还能够保证集合元素唯一
/*
* 学生类
*/
public class Student {
private String name;
private int age;
public Student() {
super();
// TODO Auto-generated constructor stub
}
public Student(String name, int age) {
super();
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 static void main(String[] args) {
//创建一个List集合
List<Student> list = new ArrayList<Student>();
//创建学生对象
Student s1 = new Student("kaka", 25) ;
Student s2 = new Student("kaka", 25) ;
Student s3 = new Student("zhangsan", 20) ;
Student s4 = new Student("lisi", 20) ;
Student s5 = new Student("wangwu", 22) ;
Student s6 = new Student("zhaoliu", 30) ;
//添加到list集合中
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
list.add(s5);
list.add(s6);
//对当前学生排序,针对List集合的比较器排序
//list集合是可以重复的
Collections.sort(list, 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 :list){
System.out.println(s.getName() + "---"+ s.getAge());
}
}
9. 模拟斗地主的洗牌和发牌_ 无序
需求:3个玩家 每一个玩家17张牌, 3张底牌
步骤:
- 有一个牌盒,创建一个牌盒 ArrayList< String >
- 装牌
- 定义花色数组 String[] colors = {} ;
- 定义点数数组 String[] numbers ={A,2,4...10,J,Q,K}
- 遍历花色和点数数组
- 花色和点数拼接,装到牌盒中
- 洗牌
- Collections的blic static void shuffle(List<?> list):针对集合中元素随机置换
- 发牌
- 三个人--->三个人都接收牌---- 每一个人都是是一个ArrayList< String > player1/player2/player3
- 规律:几个人玩的话--->角标对人的个人求余判断情况
- 判断:
- 角标值如果大于等集合的元素-3为底牌
- 如果当前角标 % 3 ==0为第一个玩家的牌
- 如果当前角标 % 3 ==1为第二个玩家的牌
- 如果当前角标 % 3 ==2为第三个玩家的牌
- 看牌
将看牌封装一个功能,lookPoker
public class PokerTest {
public static void main(String[] args) {
//创建牌盒
ArrayList<String> array = new ArrayList<String>();
//装牌
String colors[] = {
"♠","♥","♣","♦"};
String numbers [] = {
"A","2","3","4","5","6","7","8","9","10","J","Q","K"} ;
//遍历花色/点数
for(String color :colors) {
for(String number:numbers) {
String poker = color.concat(number) ;
//装进到牌盒中
array.add(poker) ;
}
}
//添加大王,和小王
array.add("小王") ;
array.add("大王") ;
//System.out.println(array);
//洗牌 Collections shuffle(List<?> list):将牌随机置换
Collections.shuffle(array);
//System.out.println(array);
//发牌
//使用集合去接受
ArrayList<String> player1 = new ArrayList<String>();
ArrayList<String> player2 = new ArrayList<String>();
ArrayList<String> player3 = new ArrayList<String>();
ArrayList<String> dipai = new ArrayList<String>();
for(int i = 0; i < array.size();i++){
//底牌
if(i >= array.size()-3){
dipai.add(array.get(i));
}else if(i %3 == 0){
//第一个玩家的
player1.add(array.get(i)) ;
}else if(i % 3 == 1){
//第二个玩家
player2.add(array.get(i));
}else if(i % 3 == 2){
// 第三个玩家
player3.add(array.get(i));
}
}
//看牌
lookPoker("玩家一:" ,player1);
lookPoker("玩家二:",player2);
lookPoker("玩家三:",player3);
lookPoker("底牌:",dipai);
}
//看牌方法
public static void lookPoker(String name,ArrayList<String> array){
System.out.print(name+ "的牌是:");
//遍历集合
for(String s : array){
System.out.print(s + " ");
}
System.out.println();
}
}
10. 模拟斗地主的洗牌和发牌_有序
需求:3个玩家 每一个玩家17张牌, 3张底牌
步骤:
- 创建一个牌盒,存储牌的编号以及对应的牌,HashMap< Integer,String>以及单独创建一个ArrayList< Integer >集合存储编号
- 装牌
- 编号从0开始 index
- 定义花色数组和点数数组
- 将花色和点数进行拼接得到牌
- 给HashMap集合添加编号对应的牌
- 给ArrayList集合单独添加编号
- 编号++
- 装小王和大王(分别给HashMap ArrayList< Integer >)
- 洗牌
- 洗的是编号:ArrayList< Integer > ,使用Collections的public static void shuffle(List<?> list):针对集合中元素随机置换
- 发牌
- 发的是编号,为了保证每个人手上的牌是排序的使用TreeSet< Integer >接收
- 判断:
- 角标值如果大于等集合的元素-3为底牌
- 如果当前角标 % 3 ==0为第一个玩家的牌
- 如果当前角标 % 3 ==1为第二个玩家的牌
- 如果当前角标 % 3 ==2为第三个玩家的牌
- 看牌
封装一个功能 ,lookPoker
public class PokerTest {
public static void main(String[] args) {
//创建一个牌盒
HashMap<Integer,String> hm = new HashMap<Integer,String>();
//存放编号
ArrayList<Integer> array = new ArrayList<Integer>();
//装牌
int index = 0;
String[] colors = {
"♠","♥","♣","♦"};
String [] numbers = {
"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
for(String number : numbers){
for(String color :colors){
String poker = color.concat(number);
hm.put(index, poker);
array.add(index);
index++;
}
}
hm.put(index, "小王");
array.add(index);
index++;
hm.put(index, "大王");
array.add(index);
//洗牌
Collections.shuffle(array);
//发牌
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<array.size(); i++){
if(i >= array.size()-3){
dipai.add(array.get(i));
}else if(i % 3 == 0){
player1.add(array.get(i));
}else if(i % 3 == 1){
player2.add(array.get(i));
}else if(i % 3 == 2){
player3.add(array.get(i));
}
}
//看牌
lookPoker("玩家一",player1,hm);
lookPoker("玩家二",player2,hm);
lookPoker("玩家三",player3,hm);
lookPoker("底牌",dipai,hm);
}
public static void lookPoker(String name,TreeSet<Integer> array,HashMap<Integer,String> hm){
System.out.print(name+"的牌是");
for(Integer i : array){
String value = hm.get(i);
System.out.print(value +" ");
}
System.out.println();
}
}