重点
1.TreeSet的Comparator排序方式
TreeSet的排序方式有2种
1.自然顺序(Comparable)
2.比较器顺序(Comparator)
public TreeSet(Comparator<? super E> comparator)
使用场景:如果元素的类型是final类型,不被重写,这个时候选择Comparator排序方式
3.如果希望有相同的元素存在,在compareTo或者compare方法,返回1就行了。
public class Demo01 {
public static void main(String[] args) {
Set\<Integer> set = new TreeSet\<Integer>(new MyComparator());
set.add(123);
set.add(12);
set.add(55);
set.add(16);
for(Integer i : set){
System.out.println(i);
}
}
}
class MyComparator implements Comparator\<Integer>{
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o2-o1;
}
}
2.TreeSet排序原理总结
TreeSet的特点:
–TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
–TreeSet排序方式有两种自然顺序和比较器顺序
-
自然顺序(Comparable)
TreeSet类的add()方法中会把存入的对象提升为Comparable类型
调用对象的compareTo()方法和集合中的对象比较
根据compareTo()方法返回的结果进行存储 -
比较器顺序(Comparator)
创建TreeSet的时候可以制定 一个Comparator
如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的规则比较
add()方法内部会自动调用Comparator接口中compare()方法排序
调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数
–两种比较方式的区别
1.TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
2.TreeSet如果传入Comparator, 就优先按照Comparator
3.Map介绍
Map是属于java.util的一个接口Map<K,V>
类型参数:
K - 映射所维护的键的类型
V - 映射值的类型
Map是将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
Map接口和Collection接口的不同
–Map是双列的,Collection是单列的
–Map的键唯一,Collection的Set是唯一的,List不是惟一的
Map:有几个常用的子类HashMap,LinkedHashMap,TreeMap,Hashtable,Properites
4.Map的功能
a>添加功能
V put(K key,V value):添加元素。
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
b>删除功能
void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回
c>判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
d>获取功能
V get(Object key):根据键获取值
Set<K> keySet():获取集合中所有键的集合
Collection<V> values():获取集合中所有值的集合
e>长度功能
int size():返回集合中的键值对的个数
5.HashMap使用注意事项
- 声明HashMap时的键值可以是任意对象
- 如果有重复的键,会把以前的替换
- 值能为空
- 键能为空,但这样写没什么意义
- put方法的返回值
- 如果键是第一次存储,就直接存储元素,返回null
- 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
6.Map的遍历,有两种方式
a>Map集合的遍历一(键找值)
//1.创建Map对象
Map<String,String> map = new HashMap<String,String>();
map.put(“name”, “刘三姐”);
map.put(“age”, “48”);
map.put(“gender”, “女”);
map.put(“height”, “1.62”);
//3.遍历
//3.1获取map所有键
Set\<String> keys = map.keySet();
//3.2遍历键
for(String key : keys){
//3.3 通过key获取值
String value = map.get(key);
//打印key&value
System.out.println(key + " : " + value);
}
b>Map集合的遍历二(键值对对象Entry找键和值)
public static void test1() {
//1.创建Map对象
Map<String,String> map = new HashMap<String,String>();
map.put(“name”, “刘三姐”);
map.put(“age”, “48”);
map.put(“gender”, “女”);
map.put(“height”, “1.62”);
//java.util.Map.Entry
/**
* Entry:称为键值对 对象
* */
Set\<Entry\<String, String>> entries = map.entrySet();
//遍历
for(Entry\<String, String> entry : entries){
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + " : " + value);
}
}
7.键值对对象找键和值源码分析
- Map.Entry理解成"键值对对象"
- Map.Entry是一个接口,它的实现类是HashMap$Node
- Map.Entry是有个key和value属性,通过get方法可以取值
- 遍历Entry的两种方法,通过迭代器和for增强
//1.创建Map
Map\<String,Integer> map = new HashMap\<String,Integer>();
map.put("zhangsan", 100);
map.put("lisi", 89);
map.put("wangwu", 1000);
//2.遍历
Set\<Entry\<String, Integer>> entries = map.entrySet();
//2.1通过增强for循环来遍历Set
/*for(Entry\<String, Integer> entry : entries){
//Map.Entry 的实现类HashMap$Node
System.out.println(entry.getClass());
System.out.println(entry.getKey() + "---" + entry.getValue());
}*/
//2.2 通过迭代器来遍历Set
Iterator\<Entry\<String, Integer>> iterator = entries.iterator();
while(iterator.hasNext()){
Entry\<String, Integer> entry = iterator.next();
System.out.println(entry.getKey() + "---" + entry.getValue());
}
8.LinkedHashMap
LinkedHashMap是存和取的顺序是一样
HashMap是存和取的顺序不是一样
LinkedHashMap它是继承HashMap
9.TreeMap
TreeMap会对键key进行排序
TreeMap的key,如果是自定义对象话,这个对象要实现Comparable接口,
或者说在new TreeMap的时候,传一个comparator参数
public class Demo01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//案例:TreeMap集合键是Student值是String
/**
* TreeMap对key进行排序
*/
test3();
}
//使用Comparator进行TreeMap的key排序
public static void test3() {
Map\<Student,String> map = new TreeMap\<Student,String>(new Comparator\<Student>() {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generated method stub
//按名字字母的倒序排序
int num = o2.name.compareTo(o1.name);
num = num == 0 ? 1 : num;//同名的可以存储
return num;
}
});
map.put(new Student("banana", 18), "gz");
map.put(new Student("cc", 18), "sz");
map.put(new Student("apple", 18), "xg");
map.put(new Student("cc", 28), "sz");
for(Entry\<Student,String> entry :map.entrySet()){
System.out.println(entry.getKey() + " - " + entry.getValue());
}
}
//使用Comparable进行TreeMap的key排序
public static void test2() {
Map\<Student,String> map = new TreeMap\<Student,String>();
map.put(new Student("banana", 18), "gz");
map.put(new Student("cc", 18), "sz");
map.put(new Student("apple", 18), "xg");
map.put(new Student("cc", 28), "sz");
for(Entry\<Student,String> entry :map.entrySet()){
System.out.println(entry.getKey() + " - " + entry.getValue());
}
}
public static void test1() {
Map\<String,String> map = new TreeMap\<String,String>();
map.put("zhangsan", "广州");
map.put("lisi", "广西");
map.put("wangwu", "湖南");
map.put("zhaoliu", "湖北");
map.put("xiaoqi", "福建");
//最方便遍历方式
//Set\<Entry\<String, String>> entries = map.entrySet();
for(Entry\<String, String> entry : map.entrySet()){
System.out.println(entry.getKey() + "--" + entry.getValue());
}
}
}
class Student implements Comparable\<Student>{
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student o) {
// TODO Auto-generated method stub
//按名字字母排序
int num = this.name.compareTo(o.name);
//同名的可以存储
num = num == 0 ? 1 : num;
return num;
}
}
10.Collections集合工具类
Collections成员方法
public static <T> void sort(List<T> list) 排序
public static <T> int binarySearch(List<?> list,T key) 二分查找
public static <T> T max(Collection<?> coll) 取大值
public static void reverse(List<?> list) 反转
public static void shuffle(List<?> list) 打乱顺序
public class Demo01 {
public static void main(String[] args) {
//Collections工具类的概述和常见方法
/**
* 1.Collection 与 Collections 区别
* Collection是一个接口
* Collections是一个类
* 2.Collections的作用针对集合操作 的工具类
*
* 3.Collections成员方法
public static <T> void sort(List<T> list) 排序
public static <T> int binarySearch(List<?> list,T key) 二分查找
public static <T> T max(Collection<?> coll)
public static void reverse(List<?> list)
public static void shuffle(List<?> list)
*/
List<Integer> list1 = new ArrayList<Integer>();
list1.add(23);
list1.add(2);
list1.add(3);
list1.add(13);
System.out.println("list1:" + list1);
//1.给list集合进行排序
//Collections.sort(list1);
//System.out.println("list1:" + list1);
//2.二分查找
//int index = Collections.binarySearch(list1, 13);
//System.out.println("13在list1中的位置:" + index);
//3.取最大值
/**
* Collection
* -List
* -Set
*/
int max = Collections.max(list1);
System.out.println("最大值:" + max);
//4.reverse 反转
Collections.reverse(list1);
System.out.println("反转后的list1" + list1);
//5.shuffle 打乱顺序
Collections.shuffle(list1);
System.out.println("打乱后的list1" + list1);
}
}
11.泛型固定下边界 【? super E】
/*泛型固定下边界 ? super E
1.回顾 【? extends E】-表示泛型固定上边界
? 表示子类,E表示父类
ArrayList.addAll(Collection<? extends Person> c)
2.【? super E】 -表示泛型固定下边界
? 表示父类,E表示的是子类
ArrayList.sort(Comparator<? super Student> c)
3.【? extends E 】针对存的操作
4.【? super E】 针对取的操作*/
练习题
1.在一个集合中存储了无序并且重复的字符串,让其有序(字母顺序),而且还不能去除重复
public static void main(String[] args) {
Set\<String> set = new TreeSet\<String>(new Comparator\<String>() {
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
int num = o1.compareTo(o2);//由小到大
num = num==0 ? 1 : num;//保存同名元素
return num;
}
});
set.add("baa");
set.add("dbb");
set.add("ccc");
set.add("ccc");
System.out.println(set);
for(String str : set){
System.out.println(str);
}
}
}
2.从键盘输入接收多个整数, 直到输入quit时结束输入. 把所有输入的整数倒序排列打印
- 掌握:
- 1.数字的倒序实现
- 2.把str转成int
public class Demo01 {
public static void main(String[] args) {
//1.创建TreeSet集合
Set\<Integer> set = new TreeSet\<Integer>(new Comparator\<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// TODO Auto-generated method stub
return o2 - o1;
}
});
//2.接收整数存在TreeSet中
System.out.println("请多次输入整数,直到输入quit时结束输入");
Scanner scanner = new Scanner(System.in);
while (true) {
String str = scanner.next();
if ("quit".equals(str)) {
break;
}
set.add(Integer.parseInt(str));
}
//3.打印集合
for(Integer i : set){
System.out.println(i);
}
}
}
3.键盘录入学生信息按照总分排序后输出在控制台
/**
* 1.创建学生类
* 添加3个学科(语文,数学,英语)成绩属性
* 添加名字属性
* 在有参构造方法中把总分算好
* 2.把n个学生添加到TreeSet中
* angle,89,98,68
* 3.TreeSet要进行总分排序
* 4.键盘输入学生信息格式:【名字,89,98,68】
* 5.当键盘输入quit,代表学生的成绩录入完毕
*
* 技巧:字符串有个split(",")方法
* 这个方法把有固定格式的字符串[angle,89,98,68]解析成数组 [angle, 89, 98, 68]
*/
public class Demo01 {
public static void main(String[] args) {
//1.创建集合
Set\<Student> set = new TreeSet\<Student>();
//2.添加元素
//2.1创建Scanner
Scanner scanner = new Scanner(System.in);
//2.2录入多个学生成绩
System.out.println("请录入学生成绩,录入的格式【名字,89,98,68】");
System.out.println("如果录入完毕,请输入quit退出");
while(true){
//2.3 获取录入学生成绩信息
//angle,89,98,68
String info = scanner.nextLine();
System.out.println("info:" + info);
//2.4 判断是否录入完毕
if(info.equals("quit")){
break;
}
//2.5 解析数据 info = "angle,89,98,68",
//把有固定格式的字符串解析成数组 [angle, 89, 98, 68]
String[] infos = info.split(",");
System.out.println(Arrays.toString(infos));
String name = infos[0];
String chineseStr = infos[1];
String mathStr = infos[2];
String englishStr = infos[3];
//把内容封装成学生对象
Student stu = new Student(name,
Integer.parseInt(chineseStr),
Integer.parseInt(mathStr),
Integer.parseInt(englishStr));
//System.out.println(Arrays.toString(infos));
//把学生放在Set中
set.add(stu);
}
// set.add(new Student("banana", 89, 89, 91));
// set.add(new Student("angle", 89, 89, 90));
// set.add(new Student("apple", 89, 89, 91));
// set.add(new Student("king", 89, 89, 89));
// set.add(new Student("banana", 89, 89, 91));
//3.遍历集合
for(Student stu : set){
System.out.println(stu);
}
}
}
public class Student implements Comparable\<Student>{
//1.创建学生类,添加3个学科(语文,数学,英语)成绩属性
private String name;
private int chinese;
private int math;
private int english;
private int totalScore;//总分
public Student() {
super();
// TODO Auto-generated constructor stub
}
/**
*
* @param name 学生名字
* @param chinese 语文成绩
* @param math 数学成绩
* @param english 英语成绩
*/
public Student(String name, int chinese, int math, int english) {
super();
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
//在构造方法中把总分先算好
this.totalScore = chinese + math + english;
}
@Override
public String toString() {
return "Student [名字=" + name + ", 语文=" + chinese + ", 数学=" + math + ", 英语=" + english
+ ", 总分=" + totalScore + "]";
}
@Override
public int compareTo(Student o) {
// TODO Auto-generated method stub
//总分排序【由大到小】
int num = o.totalScore - this.totalScore;
//如果总分一样,就按照名字排序
num = num == 0 ? this.name.compareTo(o.name) : num;
//同名的学生可能有些没法排序
num = num == 0 ? 1 : num;
return num;
}
}
4.HashMap集合键是Student,值是String
public class Demo01 {
public static void main(String[] args) {
/* 案例 :HashMap集合键是Student,值是String
键是学生对象,代表每一个学生
值是字符串对象,代表学生归属地
注意事项:
1.打印的key是student的toString方法返回的字符串
2.如果key相同,会把前面的值替换掉,但是必须是同一个对象
3.HashMap是无序的
4.new出来的都不是相同的key,因为地址不同。如果属性一样,想替换前面对应属性一样的valus时候,需要重写equals&hashcode方法
*/
Map\<Student,String> map = new HashMap\<Student,String>();
map.put(new Student("小刘", 18), "湖北");
map.put(new Student("小胡", 18), "湖南");
// Student stu = new Student("小官", 18);
// map.put(stu, "广东");
// map.put(stu, "广西");
map.put(new Student("小官", 18), "广东");
map.put(new Student("小官", 18), "广西");
//System.out.println("map:" + map);
//遍历
Set\<Entry\<Student, String>> entries = map.entrySet();
for(Entry\<Student, String> entry : entries){
System.out.println(entry.getKey() + " --- " + entry.getValue());
}
}
}
class Student{
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", 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;
}
}
5.统计字符串中每个字符出现的次数
public static void main(String[] args) {
String str = "aaaabbbccccc";
/**
* Map\<Character,Integer> map = new HashMap\<Character,Integer>();
* map.put('a',4);
* map.put('b',3);
* map.put('c',5);
*/
//1.创建存储字符次数的Map集合
Map\<Character,Integer> map = new HashMap\<Character,Integer>();
//2.遍历字符串的每一个字符
for(int i=0;i\<str.length();i++){
//3.往map里添加字符出现次数(累加)
char ch = str.charAt(i);
//map第一次出现这个字符
if(!map.containsKey(ch)){
map.put(ch, 1);
}else{
//map如果不是第一 次出现这个字符,累加+1
map.put(ch, map.get(ch) + 1);
}
}
System.out.println("map:" + map);
}
6.集合的嵌套,Map嵌套Set
/**
* 掌握: 1.HashMap嵌套HashSet,或者说Map里嵌套Set
* 2.集合嵌套的遍历
*
*/
public class Demo01 {
public static void main(String[] args) {
//集合嵌套之HashMap嵌套HashSet
/* 需求
一个学校有两个班
一个班有多个学生
通过HashMap与HashSet来实现数据存储*/
//1.创建两个班(Set)
Set\<Student> javaClass = new HashSet\<Student>();
javaClass.add(new Student("小贾", 28));
javaClass.add(new Student("小牛", 18));
Set\<Student> h5Class = new HashSet\<Student>();
h5Class.add(new Student("小丽", 28));
h5Class.add(new Student("小红", 18));
//2.创建一个学校(Map)
//Key:班级名字,Value:这个班所有学生
/***
* HashMap嵌套HashSet,或者说Map里嵌套Set
*/
Map\<String,Set\<Student>> school = new HashMap\<String,Set\<Student>>();
school.put("Java班级", javaClass);
school.put("H5班级", h5Class);
//3.遍历
//3.1遍历学校里的班级
for(Entry\<String,Set\<Student>> entry : school.entrySet()){
System.out.println("班级名称:" + entry.getKey());
//3.2 遍历班级里学生
//Set\<Student> myClass = entry.getValue();
for(Student stu : entry.getValue()){
System.out.println(stu);
}
}
}
}
class Student{
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
7.斗地主
- 功能:
* 1.准备一幅牌(54张)
* 2.洗牌(打乱牌序) shuffle方法
* 3.发牌(三个人)
* 4.留三张底牌
* 5.每个人拿到牌后,对牌进行排序
* 6.出牌…
*
* 一.发牌(每个人的牌先不排序)
* 二.发牌(每个人的牌是排序)
方法一:
public class Demo01 {
public static void main(String[] args) {
//一.发牌(每个人的牌先不排序)
// * 1.准备一幅牌(54张) 用List<String>
List<String> poker = new ArrayList<String>();
//花色
String[] colors = {"黑桃","红心","梅花","方块"};
//牌的数字
String[] nums = {"2","3","4","5","6","7","8","9","10","j","Q","K","A"};
//遍历
for(String color : colors){
for(String num : nums){
String pai = color + num;//一张牌
poker.add(pai);
}
}
//少两个王
poker.add("小王");
poker.add("大王");
System.out.println("poker" + poker);
// * 2.洗牌(打乱牌序)
Collections.shuffle(poker);
System.out.println("poker" + poker);
// * 3.随机留三张底牌
List<String> dipai = new ArrayList<String>();//底牌
Random random = new Random();
for(int i=0;i<3;i++){
//0~53;
//0~52
//0~51
int index = random.nextInt(poker.size());
String pai = poker.remove(index);
dipai.add(pai);
//System.out.println("底牌:" + pai);
}
System.out.println("底牌:" + dipai);
//抽了3张底牌,还有51张牌
// * 4.发牌(三个人) 把每个人的牌存在List集合
List<String> gaojin = new ArrayList<String>();//高进
List<String> longwu = new ArrayList<String>();//龙五
List<String> me = new ArrayList<String>();//我
for(int i=0;i<poker.size();i++){
//取牌
String pai = poker.get(i);
int mod = i % 3;
//前3张:索引0,1,2,3
if(mod == 0){
gaojin.add(pai);
}else if(mod == 1){
longwu.add(pai);
}else if(mod == 2){
me.add(pai);
}
}
// * 5.每个人拿到牌后
System.out.println("高进:" + gaojin);
System.out.println("龙五:" + longwu);
System.out.println("我:" + me);
}
}
方法二:(灵活的运用到了Map、Set、List的属性,发牌后有序)
public class Demo01 {
public static void main(String[] args) {
// TODO Auto-generated method stub
//模拟斗地主
/**
* 功能:
* 1.准备一幅牌(54张)
* 2.洗牌(打乱牌序)
* 3.发牌(三个人)
* 4.留三张底牌
* 5.每个人拿到牌后,对牌进行排序
* 6.出牌...
*
* 二.发牌(每个人的牌是排序)
*/
//1.准备一幅牌(54张)
Map<Integer,String> poker = new HashMap<Integer,String>();
//1.1花色
String[] colors = {"黑桃","红心","梅花","方块"};
//1.2牌的数字
String[] nums = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
//1.3遍历花色&数字
int index = 0;
//是进行花色排序
/*for(String color : colors){
for(String num : nums){
String pai = color + num;
//1.4 把索引和牌 添加到Map
poker.put(index, pai);
index ++;
//System.out.println(pai);
}
}*/
//进行数字排序
for(String num : nums){
for(String color : colors){
String pai = color + num;
//1.4 把索引和牌 添加到Map
poker.put(index, pai);
index ++;
//System.out.println(pai);
}
}
//1.5 添加大王小王
poker.put(index, "小王");
index++;
poker.put(index, "大王");
//1.6 遍历poker
System.out.println("===========遍历poker=========");
for(Entry<Integer,String> entry:poker.entrySet()){
System.out.println(entry.getKey() + " -- " + entry.getValue());
}
//2.洗牌
//2.1获取牌的索引
//Set<Integer> pokerKeys =poker.keySet();
//把set 转 list
List<Integer> pokerIndexs = new ArrayList<Integer>();
for(Integer i : poker.keySet()){
pokerIndexs.add(i);
}
//2.2把索引打乱
Collections.shuffle(pokerIndexs);
System.out.println("==========打乱的牌索引==========");
System.out.println("pokerIndexs:" + pokerIndexs);
//3.留底牌【前三张】
Set<Integer> dipaiIdxs = new TreeSet<Integer>();
dipaiIdxs.add(pokerIndexs.remove(0));
dipaiIdxs.add(pokerIndexs.remove(0));
dipaiIdxs.add(pokerIndexs.remove(0));
System.out.println("=========底牌索引===========");
System.out.println("dipaiIdxs:" + dipaiIdxs);
//4.发牌
Set<Integer> gaoJinIdxs = new TreeSet<Integer>();
Set<Integer> longWuIdxs = new TreeSet<Integer>();
Set<Integer> meIdxs = new TreeSet<Integer>();
for(int i = 0;i < pokerIndexs.size();i++){
//取出扑克的索引
int pokerIndex = pokerIndexs.get(i);
int mod = i % 3;
if(mod == 0){
gaoJinIdxs.add(pokerIndex);
}else if(mod == 1){
longWuIdxs.add(pokerIndex);
}else if(mod == 2){
meIdxs.add(pokerIndex);
}
}
//5.打印每个人扑克的索引
System.out.println("高进:" + gaoJinIdxs);
System.out.println("龙五:" + longWuIdxs);
System.out.println("我:" + meIdxs);
//6.看牌
lookPoker("底牌", poker, dipaiIdxs);
lookPoker("高进", poker, gaoJinIdxs);
lookPoker("龙五", poker, longWuIdxs);
lookPoker("我", poker, meIdxs);
}
//看牌
/**
*
* @param name 玩家的名字
* @param poker 完整的扑克牌
* @param playerPokerIndexs 玩家扑克牌的索引
*/
public static void lookPoker(String name,Map<Integer,String> poker,Set<Integer> playerPokerIndexs){
List<String> pokerValues = new ArrayList<String>();
//遍历玩完的扑克牌索引
for(Integer key :playerPokerIndexs){
pokerValues.add(poker.get(key));
}
System.out.println(name + ":" + pokerValues);
}
}
8.金融借款算法
本金
利息
利率:【1分=1%=0.01】【1厘=0.1%=0.001】
还款日期的计算【看代码】
public class FinanceUtil {
/**
* 返回 还款日期列表
* @param date 借款日期
* @param borrowMonth 贷款期数
* @return
*/
public static List<String> replyDateList(Date date,int borrowMonth ) {
//还款日期计算
List<String> list = new ArrayList<String>();
//1.借款日期
Date borrowDate = new Date();
//2.借款期数(借几个月)
//3.计算未来12月的还款日期
//3.1 把借款日期的年月日算出来 yyyy-MM-dd
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String str = sdf.format(borrowDate);
String[] s = str.split("-");//按规律截取字符串
int y = Integer.parseInt(s[0]);
int m = Integer.parseInt(s[1]);
int d = Integer.parseInt(s[2]);
/*System.out.println("年:" + y);
System.out.println("月:" + m);
System.out.println("日:" + d);*/
//3.2 计算未来还款日期
//i = 0,1,2,3,4,5,6,7,8,9,10,11
for (int i = 0; i < borrowMonth; i++) {
//算2月份的最大天数
//用Calendar计算
Calendar calendar = Calendar.getInstance();
calendar.set(y, m+i+1, 1);
//天数-1
calendar.add(Calendar.DAY_OF_MONTH, -1);//错误的使用了set方法,导致天数没有31天的
//取出日期中年月日
int hy = calendar.get(Calendar.YEAR);
int hm = calendar.get(Calendar.MONTH)+1;
int hd = calendar.get(Calendar.DAY_OF_MONTH);//当月的最大天数
//还款日默认情况下就是借款日
int huanMoney = d;
//借款日大于当月的最大天数
if (d > hd) {
huanMoney = hd;
}
String str2 = hy+ "-" + hm + "-" + huanMoney;
list.add(str2);
}
return list;
}
}
- 等额本息:每个月还的本金一样,利息递减
public class Repayment {
//当月本金
private double principal;
//还款期数
private int index;
//当月利息
private double interest;
//还款日期
private String date;
public Repayment() {
super();
// TODO Auto-generated constructor stub
}
public Repayment(double principal, int index, double interest, String date) {
super();
this.principal = principal;
this.index = index;
this.interest = interest;
this.date = date;
}
public double getPrincipal() {
return principal;
}
public void setPrincipal(double principal) {
this.principal = principal;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public double getInterest() {
return interest;
}
public void setInterest(double interest) {
this.interest = interest;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
@Override
public String toString() {
return "Repayment [当月本金=" + principal + ", 还款期数=" + index + ", 当月利息=" + interest + ", 还款日期=" + date
+ "]";
}
}
public class Demo01 {
public static void main(String[] args) {
//等额本息计算(按月还款-按月算)
/*等额本息(每月等额)还款计算:
1.等额本息每个月的还的本金一样,利息递减
2.公式:本金/12 + 剩余本金 * 月利息(1%)*/
System.out.println("还款方式:等额本息");
List<Repayment> list = new ArrayList<Repayment>();
//1.借款金额
double borrowMoney = 10000;
System.out.println("借了:"+borrowMoney);
//2.还款的期数
int index = 21;
System.out.println("借款期数:"+index);
//3.计算每个月还款的本金
double principal = borrowMoney / index;
//System.out.println(principal);//小数点太多了
principal = Double.parseDouble(String.format("%.2f", principal));//设置保留两位小数点
//借款日期
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String s= sdf.format(date);
//借款月利率(1分2)
double rate = 0.012;
System.out.println("月利率:"+rate);
System.out.println("借款日期:"+ s);
//小数点保留2位
//4.计算未来12个月还款数据
for (int i = 0; i < index; i++) {
//4.1计算好还款日期
//调用了我封装的方法
List<String> list2 = FinanceUtil.replyDateList(date, index);
String hdate = list2.get(i);//还款日期
//4.2设置还款期数
int hqishu = i+1;
//4.3设置当月的本金
double dbenjin;
if (i < index - 1) {
dbenjin = principal;//0-11期的应还本金
}else {
//最后一期本金
dbenjin = borrowMoney - (index - 1)*principal;
dbenjin = Double.parseDouble(String.format("%.2f", dbenjin));
}
//4.4设置利息
/**
* 公式:利息:剩余本金 * 月利息(0.012)
*/
double lixi = (borrowMoney - dbenjin*i)*rate;
lixi = Double.parseDouble(String.format("%.2f", lixi));
//把属性封装到对象
Repayment repayment = new Repayment(dbenjin,hqishu, lixi, hdate);
//把对象存到集合
list.add(repayment);
}
//5.遍历
for(Repayment re : list){
System.out.println(re);
}
}
}
- 先息后本:前面n个的只还利息,最后一个,利息+所有本金
public class Demo02 {
public static void main(String[] args) {
/*先息后本款计算:
前11个月 本金*月利息(1%)
最后一个月 本金 + 本金*月利息(1%)
*/
System.out.println("还款方式:先息后本");
List<Repayment> list = new ArrayList<Repayment>();
//1.借款金额
double borrowMoney = 10000;
System.out.println("借了:"+borrowMoney);
//2.还款的期数
int index = 12;
System.out.println("借款期数:"+index);
//3.计算每个月还款的本金
double principal = 0;
principal = Double.parseDouble(String.format("%.2f", principal));//设置保留两位小数点
//借款日期
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String s= sdf.format(date);
//借款月利率(1分2)
double rate = 0.012;
System.out.println("月利率:"+rate);
System.out.println("借款日期:"+ s);
//小数点保留2位
//4.计算未来12个月还款数据
for (int i = 0; i < 12; i++) {
//4.1计算好还款日期
//调用了我封装的方法
List<String> list2 = FinanceUtil.replyDateList(date, index);
String hdate = list2.get(i);//还款日期
//4.2设置还款期数
int hqishu = i+1;
//4.3设置当月的本金
double dbenjin;
if (i < index - 1) {
dbenjin = principal;//0-11期的应还本金
}else {
//最后一期本金
dbenjin = borrowMoney;
dbenjin = Double.parseDouble(String.format("%.2f", dbenjin));
}
//4.4设置利息
/**
* 公式:利息:剩余本金 * 月利息(0.012)
*/
double lixi = borrowMoney*rate;
lixi = Double.parseDouble(String.format("%.2f", lixi));
//把属性封装到对象
Repayment repayment = new Repayment(dbenjin,hqishu, lixi, hdate);
//把对象存到集合
list.add(repayment);
}
//5.遍历
for(Repayment re : list){
System.out.println(re);
}
}
}
面试题
1.HashMap和Hashtable区别
- Hashtable是JDK1.0版本出现的,是线程安全的,效率低,有加锁(看原码)[很少用]
- HashMap是JDK1.2版本出现的,是线程不安全的,效率高
- Hashtable不可以存储null键和null值
- HashMap可以存储null键和null值
public static void main(String[] args) {
//hashMap对象
HashMap<String,String> map = new HashMap<String,String>();
map.put("name", "gyf");
map.put(null, null);
System.out.println(map);
//Hashtable对象
Hashtable<String,String> table = new Hashtable<String,String>();
table.put("name", "gyf");
table.put(null, null);//Hashtable不可以存储null键和null值
System.out.println(table);
}
总结
通过对Set、Map的学习,对集合有了更深入的认识,对排序有了更深的印象,在斗地主案例里面,灵活的运用了Map的键值对特性,存扑克牌,然后用TreeSet集合存序号,这样得到的手牌就会自动排序,得到序号后再用ArrayList集合存序号所对应的牌,然后对比数组中的Arrays工具类,集合也有自己的工具类Collectiongs.练习了金融利息算法(包括等额本息、先息后本两种还款方式),遇到了保留小数点的问题,查阅,可以用String的format("%.2f",需要保留小数点的数)转化。自己封装了这两个方法,作为工具类。以后算利息,一行代码就可以搞定!