1、可变参数
1、概念:
是jdk1.5的新特性,应用于方法参数列表中。主要是为了解决要写很多重载方法的情况。
特点:
(1)可变参数的参数们都是相同类型的
(2)一个方法只能有一个可变参数(方法参数列表中可以同时有可变参数和非可变参数)
(3)可变参数需要放在方法参数列表的最后面
2、格式:
修饰符 返回值类型 方法名(数据类型... 变量名){
}
(和普通方法相比,在数据类型后面添加…即可)
3、可变参数的好处
是一个可变参数的反方法,可以传入任意多个参数,就不用写多个重载方法,简化代码。
4、底层原理:
可变参数的实际上是一个数组。(见下面代码)
public static void main(String[] args) {
// add();
int x = add(1, 2, 3, 4, 5, 6);
System.out.println(x);
}
// 定义一个可变参数的方法
public static int add(int... a) {
// System.out.println(a); // 输出结果是[I@1c53fd30,是一个地址值。
//从反编译工具编译该java文件得出:可变参数的实际上是一个数组
/*反编译结果
public static void main(String args[])
{
int x = add(new int[] { //调用静态方法add()
1, 2, 3, 4, 5, 6
});
System.out.println(x);
}
public static transient int add(int a[])//静态方法
{
int sum = 0;
for (int i = 0; i < a.length; i++)
sum += a[i];
return sum;
}
*/
// 遍历数组得到所有的参数
int sum = 0;
for (int i = 0; i < a.length; i++) {
sum += a[i];
}
return sum;
}
// 1.一个方法只能有一个可变参数
// public static void test01(int... a, String... b) {//报错
// }
// 2.可变参数需要放在参数列表的最后面
// public static void test01(int... a, String b) {//报错
// }
2、Collection集合类的常用方法
1、概念:
Collections是集合工具类,里面提供了很多操作集合的方法。
这个类没有看到构造方法,里面的方法全是静态方法,我们直接使用类名调用
2、常用方法
static <T> boolean addAll(Collection<?> c, T... elements) //将后面的数据添加到前面的集合中
static void shuffle(List<?> list) //随机交换集合中的元素
static void sort(List<T> list) //根据元素的自然顺序升序排
PS:第三个方法sort();若比较的是字符串,见一下代码:
ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list2, "b","a","d","bc","bb","ca");
Collections.sort(list2);
//按照字母的ASCII码值来排序,先全部按照第一个排序;多个字母的再进行比较(如果第一个相同,再比较第二个字母)
System.out.println("排序后: " + list2); // 排序后: [a, b, bb, bc, ca, d]
3、Comparator比较器
Comparator是一个接口。在Collections类中的sort();重载方法中有用到,该方法通过根据指定的排序规则来对集合中的数据进行排序。
static <T> void sort(List<T> list, Comparator<? super T> c)
PS: Comparator是一个接口,它作为sort方法的参数之一。(运用多态传入该接口的实现类对象)见以下代码。
学生类
public class Student {
private String name;
private int age;
private double socre;
//构造方法
//getter setter
//重写toString()
}
重写Comparrator接口的compare方法的类(当运用匿名内部类的时候此代码可省略)
public class StudentComparator implements Comparator<Student> {//如果此处的接口没有指定泛型,就会默认是Object类型
@Override
public int compare(Student o1, Student o2) {//此处重写Comparator接口的compare()方法
// 比较学生年龄: o1 - o2升序
// return o1.getAge() - o2.getAge();
// 比较学生年龄: o2 - o1降序
// return o2.getAge() - o1.getAge();
// 按照学生成绩降序
return (int)(o2.getSocre() - o1.getSocre());
}
}
测试类
public static void main(String[] args) {
ArrayList<Student> list = new ArrayList<>();
Student s1 = new Student("赤木晴子", 16, 99);
Student s2 = new Student("赤木刚宪", 19, 100);
Student s3 = new Student("宫城良田", 20, 59);
Collections.addAll(list, s1, s2, s3);
// static <T> void sort(List<T> list, Comparator<? super T> c) 根据指定的排序规则来对集合中的数据进行排序
// Comparator是一个接口,方法参数要接口,我们传入接口的实现类对象
StudentComparator sc = new StudentComparator();
Collections.sort(list, sc);
System.out.println("方法一");
for (Student student : list) {
System.out.println(student);
}
// 方法参数要接口,我们传入匿名内部类
Collections.sort(list, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
// // 按照学生成绩升序
return (int)(o1.getSocre() - o2.getSocre());
}
});
System.out.println("方法er");
for (Student student : list) {
System.out.println(student);
}
}
3、冒泡排序
1、原理:
相邻元素比较,大的往后放。(就像水里的泡泡往上升一样,越往上的泡泡越大)
2、分析:
分析:
第一轮:
j j+1
arr[0] 和 arr[1]
arr[1] 和 arr[2]
arr[2] 和 arr[3]
第二轮:
arr[0] 和 arr[1]
arr[1] 和 arr[2]
第三轮:
arr[0] 和 arr[1]
总结:(1)有i个元素比较,就要进行(i-1)轮比较
(2)第一轮比较次数为i-1次,其后每经过一轮,每一轮的比较次数-1;
3、代码实现
public static void main(String[] args) {
int[] arr = {5, 2, 3, 1};
// 外循环控制比较轮数
for (int i = 0; i < arr.length - 1; i++) { // i = 0,1,2
System.out.println("轮数");
// 内循环控制每轮的比较次数, j小于几就比较几次
for (int j = 0; j < arr.length - 1 - i; j++) {
// System.out.println("\t" + j + "和" + (j+1) + "比较");
// 相邻元素比较,大的往后放
if (arr[j] > arr[j+1]) {
// 前面大,后面小,交换位置
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println("排序后:" + Arrays.toString(arr));
}
4、Map集合
1、介绍
(1)Map集合是与Collection集合无关的另外一种集合接口。
(2)Map集合是存放一种表示映射关系的对象的集合,这种关系是一一对应得。
(3)这种映射关系为“键”映射到“值”的对象。
a. Map不能包含重复的键,但是值可以重复
b.每个键可以映射到最多一个值
总结:
Map集合特点:
1.保存键和值
2.键不能重复,值可以重复
3.一个键对应一个值
2、Map的常用方法
Map是一个集合,常用的方法就是增删改查
增&改 V put(K key, V value)当键不重复是添加键值对,返回null,当键存在是修改,返回被修改的数据
查 V get(Object key) 通过键获取值
**删 **V remove(Object key) 通过键删除这个键值对
查集合大小 int size() 获取map的键值对的个数
补充:boolean containsKey(String key) 判断map中是否包含指定的键,如果包含返回true
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
// V put(K key, V value) 当键不重复是添加键值对,返回null,当键存在是修改,返回被修改的数据
map.put("邓超", "孙俪");
map.put("黄晓明", "杨颖");
System.out.println(map.put("谢霆锋", "张柏芝")); //键不重复,put方法返回 null
map.put("老干爹", "老干妈");
System.out.println(map.put("谢霆锋", "王菲")); // 键重复,put方法返回 张柏芝(被修改)
System.out.println(map);
// V get(Object key) 通过键获取值
System.out.println(map.get("老干爹")); // 老干妈
// V remove(Object key) 通过键删除这个键值对
map.remove("老干爹");
System.out.println("删除后: " + map);
// int size() 获取map的键值对的个数
System.out.println(map.size());
}
3、Map的实现类HashMap:
hashMap的底层是哈希表
构造格式:
HashMap<K, V> map = new HashMap<>();
PS:(K(Key)表示键的数据类型,V(Value)表示值的数据类型)
1、遍历
Map遍历就是依次取出每个键和值(一次获取一对)
(1)键找值方式步骤:
1.获取所有的键------------->Set keySet(): 返回map中所有的键,存放到Set集合中
2.遍历获取每个键----------> for循环
3.通过键找值-----------------> V value = map.get(key)
代码实现
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("邓超", "孙俪");
map.put("黄晓明", "杨颖");
map.put("谢霆锋", "张柏芝");
map.put("老干爹", "老干妈");
// 1.获取所有的键
Set<String> keySet = map.keySet();
// 2.遍历获取每个键
for (String key : keySet) {
// 3.通过键找值
String value = map.get(key); // 核心,通过键找到值
System.out.println(key + ":::" + value);
}
}
(2)遍历Entry方式
1、Entry概念
Entry是Map接口内部的一个接口,表示键值对对象,里面会保存键和值,Entry相当于结婚证。
2、如何获取entry
Set<Map.Entry<K,V>> set集合名字 = hashMap名字.entrySet(): 获取所有的Entry
注意:(1)Map接口中没有获取一个Entry的方法,只能获取所有Entry)
(2)其中,Map.Entry<K,V>表示键值对类型;entrySet()是Map接口中返回Set集合(该集合的元素类型为键值对类型)的一个成员方法。
3、步骤:
1.得到所有的Entry-----------> Set<Map.Entry<K,V>> set集合名字 = hashMap名字.entrySet()
2.遍历得到每个Entry
3.通过Entry得到键和值----------->Entry名.getKey()得到键;Entry名.getValue()得到值
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>();
map.put("邓超", "孙俪");
map.put("黄晓明", "杨颖");
map.put("谢霆锋", "张柏芝");
map.put("老干爹", "老干妈");
// 1.得到所有的Entry
Set<Map.Entry<String, String>> entrySet = map.entrySet();
// 2.遍历得到每个Entry
for (Map.Entry<String, String> entry : entrySet) {
// 3.通过Entry得到键和值
System.out.println(entry.getKey() + "==" + entry.getValue());
}
}
2、HashMap存储自定义类型
也就是保证hashMap集合的元素种的键不重复。又因为hashSet的底层是哈希表,所以要保证键不重复,则需要重写键的hashCode和equals方法
应用举例:
需求:每位学生(姓名,年龄)都有自己的家庭住址。那么,既然有对应关系,则将学生对象和家庭住址存储到map集合中。学生作为键, 家庭住址作为值。
学生类
public class Student {
private String name;
private int age;
//构造方法
//getter setter
//重写toString()
//需要重写键的hashCode和equals方法
@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;
}
public static void main(String[] args) {
// 1.定义学生类
// 2.创建一个Map用于存放学生
HashMap<Student, String> map = new HashMap<>();
// 3.创建4个学生存储到Map中
Student s1 = new Student("流川枫", 18);
Student s2 = new Student("樱木花道", 17);
Student s3 = new Student("赤木晴子", 16);
Student s4 = new Student("三井寿", 19);
Student s5 = new Student("三井寿", 19);
map.put(s1, "北海道");
map.put(s2, "东京");
map.put(s3, "大版");
map.put(s4, "名古屋");
map.put(s5, "广岛");
// 4.遍历map
// 1.键找值方式
Set<Student> keySet = map.keySet();
for (Student key : keySet) {
String value = map.get(key);
System.out.println(key + " == " + value);
}
System.out.println("-------------");
// 2.Entry方式
Set<Map.Entry<Student, String>> entrySet = map.entrySet();
for (Map.Entry<Student, String> entry : entrySet) {
System.out.println(entry.getKey() + "::" + entry.getValue());
}
}
3、HashMap的应用场景以及其常用常用方法和遍历的综合应用
当有对应关系的时候就使用map。
应用举例:
需求:计算一个字符串中每个字符出现次数。
分析:
一个字母会对应一个次数,有对应关系就使用Map集合来存储,字母作为键,次数作为值
实现步骤:
1.定义一个字符串
2.创建一个Map,字母作为键,次数作为值
3.遍历字符串,得到每个字母
4.如果map中没有这个字母,次数设置为1次
5.如果map中有这个字母,次数+1
6.遍历map集合
public static void main(String[] args) {
// 1.定义一个字符串
String str = "bzcbzaabAaacb";
// 2.创建一个Map,字母作为键,次数作为值
HashMap<Character, Integer> map = new HashMap<>();
// 3.遍历字符串,得到每个字母
for (int i = 0; i < str.length(); i++) {
// 通过索引得到字符
char c = str.charAt(i);
// Map方法: boolean containsKey(Object key) 判断map是否有这个键
if (map.containsKey(c)) {
// 5.如果map中有这个字母,次数+1
// 通过键找值,得到字符c之前已有的次数
int cout = map.get(c);
// 次数+1
map.put(c, cout + 1);
} else {
// 4.如果map中没有这个字母,次数设置为1次
map.put(c, 1);
}
}
// 6.遍历map集合
// Entry方式
Set<Map.Entry<Character, Integer>> entrySet = map.entrySet();
for (Map.Entry<Character, Integer> entry : entrySet) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
4、图书馆管理系统
/*
功能分析:
1.功能选择界面
2.初始化书籍
3.查看书籍
4.添加书籍
5.删除书籍
6.修改书籍
目标:实现 1.功能选择界面
打印输出相应字符串即可
使用键盘输入
根据用户的输入进行选择
目标:实现 2.初始化书籍
1.定义Book书籍类
2.创建一个名著集合,存储两本名著
3.创建一个it书籍集合,存储两本it书籍
4.创建一个Map,键是书籍类型,值就是对应的书籍集合
5.添加对应的数据到Map集合中
目标:实现 3.查看书籍
遍历map集合
目标:实现 4.添加书籍
输入要添加书籍的类型
输入要添加的书名
输入要添加书的价格
创建Book对象
添加到对应的ArrayList集合中
目标: 实现 5.删除书籍
输入要删除书籍的类型
输入要删除的书名
通过类型找到书籍的集合
从集合中删除这本数
目标: 实现 6.修改书籍
输入要修改书籍的类型
输入要修改书籍的书名
输入新的书名
输入新的价格
通过类型找到书籍的集合
遍历书籍集合找到要修改的书籍
修改书籍
*/
public static void main(String[] args) {
// 2.初始化书籍
// 1.定义Book书籍类
// 2.创建一个名著集合,存储两本名著
ArrayList<Book> mz = new ArrayList<>();
mz.add(new Book("西游记", 19));
mz.add(new Book("水浒传", 29));
// 3.创建一个it书籍集合,存储两本it书籍
ArrayList<Book> it = new ArrayList<>();
it.add(new Book("Java入门到精通", 99));
it.add(new Book("PHP入门到精通", 9.9));
// 4.创建一个Map,键是书籍类型,值就是对应的书籍集合
HashMap<String, ArrayList<Book>> map = new HashMap<>();
// 5.添加对应的数据到Map集合中
map.put("名著", mz);
map.put("it书籍", it);
// 让功能选择界面可以循环多次选择
while (true) {
// 1.功能选择界面, 打印输出相应字符串即可
System.out.println("--------欢迎来到图书管理系统--------");
System.out.println("1.查看书籍");
System.out.println("2.添加书籍");
System.out.println("3.删除书籍");
System.out.println("4.修改书籍");
System.out.println("5.退出");
// 使用键盘输入
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的选择:");
int operator = sc.nextInt();
// 根据用户的输入进行选择
switch (operator) {
case 1:
showAllBooks(map);
break;
case 2:
addBook(map);
break;
case 3:
deleteBook(map);
break;
case 4:
updateBook(map);
break;
case 5:
System.out.println("大爷,请慢走,欢迎下次再来!");
System.exit(0);
break;
default:
System.out.println("大爷,你的操作不存在.请不要乱来");
break;
}
}
}
private static void updateBook(HashMap<String, ArrayList<Book>> map) {
// 目标: 实现 6.修改书籍
Scanner sc = new Scanner(System.in);
// 输入要修改书籍的类型
System.out.println("请输入要修改书籍的类型");
String type = sc.next();
// 输入要修改书籍的书名
System.out.println("请输入要修改书籍的书名");
String oldName = sc.next();
// 输入新的书名
System.out.println("请输入新的书名");
String newName = sc.next();
// 输入新的价格
System.out.println("请输入新的价格");
double newPrice = sc.nextDouble();
// 通过类型找到书籍的集合
ArrayList<Book> list = map.get(type);
if (list == null) {
System.out.println("要修改的书籍类型不存在");
return;
}
// 遍历书籍集合找到要修改的书籍
for (int i = 0; i < list.size(); i++) {
Book book = list.get(i);
if (book.getName().equals(oldName)) {
// 找到了要修改的书籍
// 修改书籍
book.setName(newName);
book.setPrice(newPrice);
System.out.println("修改" + oldName + "成功");
return;
}
}
System.out.println("没有找要修改的书籍" + oldName);
}
private static void deleteBook(HashMap<String, ArrayList<Book>> map) {
// 目标: 实现 5.删除书籍
Scanner sc = new Scanner(System.in);
// 输入要删除书籍的类型
System.out.println("请输入要删除书籍的类型");
String type = sc.next();
// 输入要删除的书名
System.out.println("请输入要删除的书名");
String name = sc.next();
// 通过类型找到书籍的集合
ArrayList<Book> list = map.get(type);
if (list == null) {
System.out.println("没有这个类型的书籍");
return;
}
// 从集合中删除这本数
for (int i = 0; i < list.size(); i++) {
Book book = list.get(i);
if (book.getName().equals(name)) {
// 找到要删除的书籍,并删除
list.remove(i);
System.out.println("删除" + name + "成功");
return ; // 结束这个方法
}
}
System.out.println("没有这本书籍" + name);
}
private static void addBook(HashMap<String, ArrayList<Book>> map) {
// 目标:实现 4.添加书籍
Scanner sc = new Scanner(System.in);
// 输入要添加书籍的类型
System.out.println("请输入要添加书籍的类型");
String type = sc.next();
// 输入要添加的书名
System.out.println("请输入要添加的书名");
String name = sc.next();
// 输入要添加书的价格
System.out.println("请输入要添加书的价格");
double price = sc.nextDouble();
// 创建Book对象
Book book = new Book(name, price);
// 通过书籍类型,【找到】书籍集合
ArrayList<Book> list = map.get(type);
// 如果list为null说明,没有这种类型的书籍
if (list == null) {
list = new ArrayList<>();
map.put(type, list);
}
// 判断书籍是否存在
// 做一个标记,表示这本书是否存在,false表示不存在
boolean exists = false;
for (Book b : list) {
if (b.getName().equals(name)) {
// 书名相同;
exists = true;
break; // 一旦书名相同,就是重复的书籍,不需要往后面判断啦
}
}
if (exists) {
// 如果存在,就不添加
System.out.println(name + "书籍已经存在");
} else {
// 如果不存在,就添加
// 添加到对应的ArrayList集合中
list.add(book);
System.out.println("添加" + name + "书籍成功");
}
}
private static void showAllBooks(HashMap<String, ArrayList<Book>> map) {
System.out.println("类型\t\t书名\t价格");
// 遍历Map,使用Entry方式
// 1.得到所有的Entry
Set<Map.Entry<String, ArrayList<Book>>> entrySet = map.entrySet();
// 2.遍历得到每个Entry
for (Map.Entry<String, ArrayList<Book>> entry : entrySet) {
// 打印键
System.out.println(entry.getKey());
// 得到值(ArrayList集合)
ArrayList<Book> value = entry.getValue();
// 遍历打印ArrayList
for (Book book : value) {
System.out.println("\t\t\t" +book.getName() + "\t" + book.getPrice());
}
}
}