case后面必须是一个常量表达式
switch语句的判断条件可以接受int 、byte 、short、char、类型,jdk1.7以后支持String类型
一旦case匹配,就会按顺序执行后面代码,知道遇到break为止
swtich建议判断固定值,if建议判断区间范围
for 一般用于与次数、个数相关的循环
while 没法确定循环次数
do while
do{
}
break(终止,打断) continue(继续)
break :选择结构(switch)和循环结构
continue:循环结构(结束本次循环继续执行下一次循环)
给循环取名字
控制台随机打印一个大写字母
控制台输入一个字符,判断是否为英文字母
控制台输入一个年费份,判断该年份是闰年还是平年
控制台输入一个百分制成绩,判断该成绩的等级
90~100 ->‘A’ 60~89 ->‘B’ 60以下->‘C’
控制台输入你的薪资,判断你回家的方式
sal>15000 “坐飞机”
控制台打印所有的水仙花数(三种循环结构)
利用循环完成累加案例:
1+2+3+4…+100
计算PI的值
9+99+999+…+99999999(8个9)
折纸超过珠穆朗玛峰的高度利用死循环
定义方法,打印M行列的(*)图案
定义方法,打印乘法口诀表
百钱百鸡 公:5 母:3 小:1/3
控制台输入一个不限位数的整数,判断是否为欸回文数
重构双色球案例(解决红球重复的问题两种方式)
利用递归求出处第N个斐波那契数列
猜字母案例
面向对象
面向对象思想:
有没有这个对象
这个对象具不具备这样的功能
面向对象开发:
就是指不断的创建对象,使用对象,指挥对象做事情
有对象就找这个对象做事情,没有对象就自己创建对象使其拥有这个功能,其他人也可以使用这个对象
面向对象设计:
其实就是在管理和维护对象之间的管理
面向对象特征:
封装
继承
多态
抽象
类和对象的关系
用Java语言对现实生活中的事物进行描述,可以通过类的形式来体现,对于事物的描述通常只关注两个方面
一个是属性,一个是行为(功能和方法),只需要明确该类事物的属性和行为定义在类中即可
类:对某一类事物的描述(属性、行为)
对象:该类事物中一个实实在在的个体(实体)
引用类型 引用变量 八大基本类型
定义类就是定义该类的成员
定义属性就是定义成员变量
成员变量定义在类中,整个类都可以访问
局部变量定义在方法中(语句中/局部代码块),
只在所属的区域有效
成员变量存在于堆内存的对象当中
局部变量存在于栈内存的方法当中
成员变量随着对象的创建而存在,随着对象的消失而消失
局部变量随着所属区域的执行而存在,随着所属区域的结束而释放
成员变量都有默认的初始化值
局部变量没有默认的初始化值
一个.Java文件里面最多只能有一个public修饰的类并且public修饰的类类名要与.java的文件名一致
private:私有的,是一个权限修饰符。用于修饰成员私有的内容
重载:方法名相同,参数列表不同的
四种初始化
1,默认初始化
2,显示初始化
3,构造初始化
4,方法初始化
this关键字
用法一:
当一个类中的成员变量和局部变量重名时,
可以使用关键字this来区分
this:代表对象,代表当前对象
this就是所在方法所属对象的引用
简单说:那个对象调用了this所在的方法,
this就代表哪个对象
在构造器中用this调用构造器必须放在第一行(语法规则)
static关键字(静态的)
static是一个修饰符,同于修饰成员
static修饰的成员被所有的对象所共享
static优先于对象而存在,因为static修饰的成员随着类的加载就已经存在了
static修饰的成员多了一种调用方式,可以直接被类名调用,类名.静态成员
static修饰的数据是共享的数据,对象中存储的数据是对象中特有的数据
随着类的加载而执行,给类进行初始化
static{
}
给全体对象进行初始化
{
}
两个变量的生命周期不同
成员变量随着对象的创建而存在,随着对象的被回收而释放
静态变量随着类的加载而存在,随着类的消失而消失
调用方式不同
成员变量只能被对象调用
静态变量可以被对象调用,也可以被类名调用(最佳方式是被类名调用)
别名不同
成员变量也叫实例变量
静态变量也叫作类变量
数据的存储位置不同
成员变量数据存储在堆内存的对象当中,所以也叫做对象的特有数据
静态变量存储在方法区的静态方法区中(数据共享区)所以也叫做对象的共享数据
静态什么时候用
静态变量
当分析对象中所具备的成员变量的值都是相同的,这时这个成员变量可以被静态修饰,只要数据在对象中是不同的,就是对象的特有数据,必须存储在对象当中,是非静态的,如果是相同的数据,对象不需要修改,只需要使用即可,不需要存储在对象中,那么就定义成静态的
静态方法
方法是否使用静态修饰就参考一点,该方法的功能是否访问到对象的特有数据,如果有,就定义成非静态的,如果没有,就定义成静态的。
super必须在第一行
单继承和多继承
多层继承
1)成员变量
两个类中存在共性内容
子父类中成员重名,
this和super的用法极为相似
this:代表一个本类对象的引用
super:代表的是一个父类的空间
2)成员方法
当子类中出现成员方法一模一样的情况,会运行子类中的方法,这种现象成为覆盖操作,也称为方法的重写,这是方法在子父类中的特性
方法的特性有两个:
重载(overload):同一个类中
重写(override):子类中,覆盖也叫重写
重写的注意事项:
1)子类重写父类的方法时,子类权限必须大于等于父类的权限
2)静态只能覆盖静态或者被静态覆盖
3)构造器(不能继承,但可以调用)
在子类构造器的第一行会有一个默认的隐式构造器super(),调用的就是父类的无参构造器
如果父类中没有无参构造器,就必须在子类构造器的第一行使用super明确的调用父类的有参构造器。
子类继承了父类,获取到父类中的内容(属性),所以子类在使用父类的内容之前,要先看父类是如何对自己的内容进行初始化的,所以子类在构造对象时必须访问父类的构造器,为了完成这个必须的动作在子类的构造器中加入super()语句,如果父类中没有无参构造器,那么必须在子类构造器中使用super明确的调用父类的有参构造器
同时子类构造器中如果使用this调用了本类的其他构造器,那么super就没用了(不存在了),因为super和this都必须定义在第一行,所以只能有一个,但是可以保证的是,子类中肯定会有其它构造器访问了父类的构造器
对象在内存中的实例化过程:
Person p = new Person();
final是一个修饰符,可以修饰类,方法,变量
final修饰的类不可以被继承(String/Integer/Math…)
final修饰的方法不可以被覆盖(重写)
final修饰的变量是一个常量,只能赋值一次,成员变量一旦被final修饰之后就是固定不变的,是所有对象能够共享的内容,所以一般加上static修饰
(抽象:abstract 笼统、模糊、看不懂、不具体)
没有具体的方法体
特点:
有 super()调用父类的构造器 如果继承了抽象类当做父类那么该抽象类的构造器可以给子类进行初始化)
可以,但是很少见,目的是不让创建该类的对象。
适配器类(典型的抽象类,没有抽象方法)
abstract class Demo{
void show1(){}
void show2(){}
}
private不行,必须得要子类覆盖,
static 不行,
final不行,不可以被覆盖
一定是父类,一定有子类
相同点:
抽象类和一般类都是用来描述事物的,都在内部定义了成员
不同点:
1)一般类有足够的信息描述事物
抽象类描述事物的信息可能不足
2)一般类中不能定义抽象方法,只能定义非抽象方法
抽象类中可以定义抽象方法,也可以定义非抽象方法
3)一般类可以被实例化
抽象类不可以被实例化
定义接口的格式:interface 接口名{}
接口中的成员修饰符都是固定的:
成员变量都是成员常量:public static final
成员方法:public abstract
类和类之间的关系:继承关系
类和接口之间是实现关系(implements)
class A{}
interface B{}
class c extends A{}
class D implements B{}
本质上实现就是继承
接口也不可以实例化,只能又实现了接口的子类(实现类)覆盖了接口中所有的抽象方法后,该子类才可以实例化,否则该类依旧是一个抽象类
接口的出现将“多继承”通过另外一种形式体现出来即“多实现”
接口本质上还是一个类
同时实现两个接口类
有一种情况不可以
接口中的方法就只有返回值类型不同时
一个类在继承一个类的同时可以实现多个接口
接口是一个特殊的抽象类(纯抽象类)
接口是程序的功能扩展
接口的出现降低了耦合性
耦合性:块间联系,指的是软件系统结构中各个模块之间相互联系紧密程度的一种度量
内聚性:又叫块内联系,指的是模块内部各个元素彼此结合紧密程度的一种度量
接口可以用来多实现
类与接口之间是实现关系,而且一个类可以在继承一个类的同时实现多个方法
接口中的属性默认都是常量,而且是public static final修饰的
接口中的方法一定是public abstract 修饰(可以省略不写)\
接口和接口之间可以有继承关系,多继承。
接口中不可以定义构造器
抽象类和接口的区别
抽象类需要被继承,而且只能单继承
接口需要被实现,并且可以多实现
抽象类中可以定义抽象方法和非抽象方法
子类继承后可以直接使用非抽象方法
接口中只能定义抽象方法,必须由子类去实现
抽象类的继承,是is a关系,在定义该体系的基本共性
接口的实现是like a在定义该体系中的格外功能
方法的多态:方法的重载
对象的多态:父类型的引用指向子类的对象
提高了代码的扩展性,前期定义的代码可以使用后期的内容
子类特有的方法不能使用
自动类型提升(基本数据类型)
强转
向上转型(引用类型)
向下转型
instanceof运算符:
java中的instanceof是一个二元运算符,它的作用是用来判断instanceof运算符左边的对象是否属于右边类的实例
编译时:参考引用类型变量所属的类中是否有调用的成员变量,有就编译通过,没有,编译失败
运行时:参考引用类型变量所属的类中是否有调用的成员变量,并运行该所属类中成员变量
简单说编译和运行都看的是赋值符号的左边
编译时:参考引用类型变量所属的类中是否有调用的成员方法,有,编译通过,没有,编译失败
运行时:参考对象所属的类中是否有调用的方法并运行
简单说:编译看左边,运行看右边
修饰java类、属性、方法的访问可见范围
类内 包内 子类 任意
public √ √ √ √
protected √ √ √
默认(default) √ √
private √
private:私有的,仅仅在类的内部可见
public:公有的,任意位置可见
protected:受保护的,在同一个包中和子类中可见
JavaBean规范:
所有的属性要私有化
提供默认的构造方法
提供get和set方法
实现Serializable接口(序列化接口)
jdbc连接数据库过程
输出对象后面默认的是tostring();
class A {show() {}}
class
java默认继承Object类,java类都继承了Object类的属性和方法
toString() hashCode() equals()
默认返回值为String类型 类名全称@hashCode(0x)
这两个在Object类中都是比较引用地址是否相同
比较两个对象是否相等:“引用相等” ”对象相等“
引用相等:比的是对象的地址(引用地址、物理地址)
比的是是否为同一个对象
对象相等:比的是对象的数据,比的是对象的内容
== 比的是引用相等Object类中的equals()方法比的是:”引用相等“
java.lang包下的类不需要导包
String重写了Object类中的toString
String类型的字面量保存在内存的常量池中,常量池有优化机制,会把相同的字面量优化成同一个,所有引用的是用一个
String s1 = "abc";//常量池
String s2 = new String("abc");//堆中
比较String对象的内容是否相等可以使用重写之后equals()
Object类中的equals()方法比较的是“引用相等"
建议覆盖:实现对象内容(对象的数据)的比较
1.覆盖规则
自反性
自己和自己比结果要为TRUE,x.equals(x)->true
对称性
x.equals(y)->true y.equals(x)->true
传递性
x.equals(y)->true y.equals(z)->true x.equals(z)->true
一致性
x.equals(y)一开始的结果为true,后期只要不修改x和y的属性值,那么x.equals(y)结果依然是true
原则上不用的对象调用Object类中hashCode()返回的哈希值(散列表)是不同的
1)hashCode()要和equals()方法一同覆盖(sun公司规定的)
a.当两个对象equals()比较为true,应该具有相同的hashCode值
b.当为flase,应该具有不同的hashCode值
c.hashCode值要稳定,一个对象创建以后就不应该在发生变化
2)一般使用对象的OID值作为hashCode值,OID是对象的唯一编号,在项目中都是根据数据生成一个OID值,该数据就是数据库的主键(唯一约束性)
可以重写
String类:char[]+操作
数组里面本身这个类中没有方法
char[]本身就是一串字符,java中可以作为字符串
char[] 只读数据,没有操作(方法)
一串字符就是字符串:
String/char[]/StringBuffer/StringBuilder
字符串的自变量默认都是String类型 “abc”
字符串的常量:static final
String内部就是一个char[]
String有一个原则,对象内容不变,String对象永远不变,这样的规定使字符串使用起来跟基本类型一样
String字面量相同到时候,会替换为同一个String对象的引用,常量池会优化为同一个字符串
比较字符串的内容使用重写后的equals()方法
String类中的常用方法:
原则:String类中方法使字符串有了变化就要返回一个新的String对象,不变化就返回原字符串
a.String字符串覆盖了Object类中equals()/hashCode()/toString()
b.String字符串中所有的字符串都有下标,下标从0开始到length()-1结束
c.常用的方法
charAt():获取指定下标的字符
indexOf():获取指定字符的下标
lastIndexOf():查看给定字符串在当前字符串中最后一次出现的位置
toUpperCase():将当前字符串中所有的小写字母转换为大写字母
trim():去除当前字符串中两边的空白
startsWith():判断当前字符串是否以给定的字符串开始
endsWith():判断当前字符串是否以给定的字符串结尾
length():获取当前字符串的长度
equals():比较两个字符串的内容是否相等
equalsIgnoreCase():忽略英文大小写比较两个字符串的内容
substring():截取字符串,从给定位置截取到给定位置
toCharArray():将给定的字符串转换为对应的字符数组
getBytes():根据给定的字符集将当前字符串转换为对应的字节序列并返回
/**
将字符串存储到文件当中必须将其转换为对应的字符序列后才
可以存入所谓的字节序列就是一个byte类型的数组
*/
byte[] gbk = str.getByte("GBK")
package JavaSE.day01;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
/* 将字符串转换为字节码称为编码
* 编码和解码的时候指定的字符集要一致
* 编码集
*/
public class StringDemo04 {
public static void main(String[] args) throws UnsupportedEncodingException {
String str = "我爱Java";
/*
* 将字符串存储到文件当中
* 必须将其转换为对应的字符序
* 列后才可以存入所谓的字节序列就是
* 一个byte类型的数组
*/
byte[] gbk = str.getBytes("GBK");
System.out.println(Arrays.toString(gbk));
byte[] utf = str.getBytes("UTF-8");
System.out.println(utf.length);
/*
* UTF-8字符集中汉字占三个字节
* GBK字符集中汉字占两个字节
*
*/
/*
* String的构造方法
* String(byte[] data,String charSetName)
* 将给定的字节数组按照给定的字符集
* 转换为对应的字符串
*/
String gbkStr = new String(gbk, "GBK");
System.out.println(gbkStr);
String utfStr = new String(utf, "UTF-8");
System.out.println(utfStr);
String str1 = new String(utf, "GBK");
System.out.println(str1);
}
}
package JavaSE.day01;
public class StringDemo05 {
public static void main(String[] args) {
}
/**
* 反转累加
* 空格
* @param string
* @return
*/
public static boolean huiwen(String string){
boolean flag = true;
for (int i = 0; i < string.length() / 2; i++){
if (string.charAt(i) != string.charAt(string.length() - 1 - i)) {
System.out.println("不是回文数!");
flag = false;
}
}
return flag;
}
/*
* '人'+""->"人"
* "人" + '好' ->"人好"
* "人好" + '个' ->"人好个"
*
*/
public static String reverse(String str) {
String str1 = "";
for (int i = 0; i < str.length(); i++) {
str1 = str1 + str.charAt(i);
}
return str1;
}
}
负责字符串的匹配处理(一般用于验证字符串的格式)
书写格式:
^正则表达式$
字符集:
[123456789] 表示123456789其中之一
[1-9] 表示1-9得数(同上个)
[^12345] 表示除了12345之外的所有
[a-z] 表示a-z之间的字符
[0-9a-zA-Z] 表示0-9a-zA-Z其中之一
0[xX] [0-9a-f] 表示整数16进制
{6} 表示出现了6次
{8,10} 表示出现了8-10次
表示8-15位数字、字母、下划线组成的密码:
正则表达式本身也是一个字符串
String regex = "^[0-9a-zA-Z_]{8,15}$"
预定义字符集:
\d 表示[0-9]
. 表示任意字符
\w 表示单词字符[0-9a-zA-Z]
\s 表示匹配空白 \t \n \r \b
\D 表示非数字
\S 表示非空白
\W 表示非单词字符
{m,n} 表示出现了m到n次
{n} 表示出现了n次
? 表示出现了0-1次
+ 表示出现了1次以上
*表示出现了0-n次
| 表示或者
& 表示并且
举例:
String regex = "^[0-9]{6}$"
String regex = "^[0-9a-zA-Z]{8,16}$";
= "\\w{8,16}";
package JavaSE.day01;
import java.util.Scanner;
public class RegexDemo02 {
public static void main(String[] args) {
String regex = "^\\d{15}(\\d{2}[0-9X])?$";
Scanner scanner = new Scanner(System.in);
String codeString;
while (true) {
System.out.println("请输入你的身份证号码:");
codeString = scanner.nextLine();
if (codeString.matches(regex)) {
System.out.println("身份证号码合法:"+ codeString);
break;
}
}
}
}
将当前字符串中满足正则表达式的部分替换为给定字符串
package JavaSE.day01;
import java.util.Arrays;
public class RegexDemo03 {
public static void main(String[] args) {
/*
* +String replaceAll(String regex,
* String replacament)
* 将当前字符串中满足正则表达式
* 的部分替换为给定字符串
*
*/
String string = "QWE123YUI456OPA90PIL44";
//将上述字符串中满足数字的部分替换为#NUMBER#
String str1 = string.replaceAll("\\d+", "#NUMBER#");
System.out.println(str1);
//和谐用语
String regex = "(马化腾|SB|CNM|坑B|草)";
String massage = "我草!你个坑B!大sb!";
massage = massage.toUpperCase().replaceAll(regex, "***");
System.out.println(massage);
}
}
将给定字符重复指定次数返回
将当前字符串进行拆分
join():相当于split方法的反操作将给定数组中每一项按照给定的字符串连接在一起
将给定字符串str的左侧添加若干个给定的字符chs,以使当前给定的字符串达到给定 的长度size
package day02;
import java.util.Arrays;
import org.apache.commons.lang3.StringUtils;
public class StringUtilsDemo {
/**
* commons-lang 该包是由Apache组织提供的
* 用于扩展java中的lang包中的一些类的功能
*/
public static void main(String[] args) {
/*
* String repeat(String str,int repeat)
* 将给定的字符串重复次数返回
*/
String repeat =
StringUtils.repeat("abc", 5);
System.out.println(repeat);
/*
* 将当前字符串进行拆分
* String[] ary = str.split(",");
*/
String str = "123,456,789";
String[] ary = str.split(",");
System.out.println(Arrays.toString(ary));
/*
* join():相当于split方法的反操作
* 将给定数组中每一项按照给定的字符串
* 连接在一起
*/
String join = StringUtils.join(ary, ".");
System.out.println(join);
/*
* String leftPad(String str,int size,char chs)
* 将给定字符串str的左侧添加若干个给定的
* 字符chs,以使当前给定的字符串达到给定
* 的长度size
*/
String str1 = "12345";
String leftPad =
StringUtils.leftPad(str1, 10, '*');
System.out.println(leftPad);
//String rightPad(String str,int size,char chs)
}
}
package day02;
public class StringDemo {
/**
* 字符串不变对象的利弊
* 好处:最大程度的重用,节省空间
* 弊端:对于频繁的修改字符串内容时,
* 会创建若干个对象
* (有可能出现堆内存溢出)
*/
public static void main(String[] args) {
String str = "a";
// for (int i = 0; i < 1000; i++) {
// str += str;
//
// }
// System.out.println(str);
//OutOfMemoryErro
//利用StringBuilder(缓存字符串)来进行处理
//利用构造器将String类型的str转换为StringBuilder
StringBuffer builder = new StringBuffer(str);
for (int i = 0; i < 1000; i++) {
builder.append("a");
}
//好处就是自始至终只有一个StringBuilder对象
System.out.println(builder);
}
}
String = char[] +操作
数组是不变的(一旦改变就不是原来的数组对象)
StringBuilder = char[] +操作
数组的内容是可变的,如果长度不够,会利用变长算法来维护,自动扩容
StringBuilder是一个用来修改字符串的类,是一个变长字符序列
StringBuilder jdk1.5 效率比较高 线程不安全
StringBuffer jdk1.0 效率比较低 线程安全
StringBuilder类中常用的方法:
StringBuilder对象本身的引用(表明是一个对象)
如果我们的软件需要大量的字符串处理,建议使用StringBuilder
package day02;
public class StringBuilderDemo01 {
/**
* 对字符串的操作有以下几种:
* 增:append()
* 删:delete()
* 改:replace()
* 插:insert()
*/
public static void main(String[] args) {
String str = "好好学习java";
StringBuilder builder =
new StringBuilder(str);
/*
* StringBuilder append(String str)
* 想当前字符串的末尾追加给定的字符串
* "好好学习java,为了找个女朋友"
*/
builder.append(",为了找到女朋友");
System.out.println(builder);
/*
* StringBuilder replace
* (int start,int end,String str)
* 当前字符串中给定范围的字符串替换为给定的字符串
* "好好学习java,为了改变世界"
* 前包后不包
*/
builder.replace(11, 16, "改变世界");
System.out.println(builder);
/*
* StringBuilder delete
* (int start,int end)
* 当前字符串中给定范围的字符串删除
* ",为了改变世界"
* 前包后不包
*/
builder.delete(0, 8);
System.out.println(builder);
/*
* StringBuilder insert
* (int offset,String str)
* 将给定的字符串插入到给定位置
* "活着,就是为了改变世界"
* 前包后不包
*/
builder.insert(0, "活着");
builder.insert(0, "就是");
System.out.println(builder/* .toString() */);
}
}
package day02;
public class StringBuilderMedo02 {
public static void main(String[] args) {
String str = "上海自来水来自海上";
/*
* StringBuilder reverse()
* 将当前字符串进行反转
*/
StringBuilder str1 = new StringBuilder(str);
StringBuilder str2 = new StringBuilder(str);
str1.reverse();
System.out.println(str1);
/*
* StringBuilder并没有重写equals()方法
* 所以要比较字符串是否相同,可以先将其转换为
* String类型再比较
*/
if (str1.toString().equals(str2.toString())) {
System.out.println("是回文数");
}else {
System.out.println("不是回文数");
}
}
}
package day02;
public class StringBuilderDemo03 {
public static void main(String[] args) {
System.out.println(testString(60000));
System.out.println(testStringBuilder(60000));
}
/**
* 测试String和StringBuilder的性能
*/
public static long testString(int n) {
String str = "";
long start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
str += "abc";
}
long end = System.currentTimeMillis();
return end - start;
}
//测试StringBuilder的性能
public static long testStringBuilder(int n) {
String str = "";
StringBuilder builder = new StringBuilder(str);
long start = System.currentTimeMillis();
for (int i = 0; i < n; i++) {
builder.append("abc");
}
long end = System.currentTimeMillis();
return end - start;
}
}
内部类:一个类声明在类体当中
a.使用static修饰,声明在类体中
b.静态内部类可以访问外部类的静态成员
a.声明在类体中,不使用static修饰,具有类的特征
也就是说,必须有外部类的实例才能创建内部类的实例
b.内部类的实例可以访问外部类的成员变量
package day04;
import day04.Goo.Moo;
public class InnerClassDemo {
//成员内部类
public static void main(String[] args) {
/*
* 成员内部类的实例必须
* 通过外部类的实例才能创建
*/
Goo goo = new Goo();
Moo moo = goo.new Moo();
System.out.println(moo.add());
Goo goo1 = new Goo();
goo1.a = 2;
Moo moo1 = goo1.new Moo();
System.out.println(moo1.add());
}
}
/*
* 成员内部类就是普通的内部类,但是不加static修饰,
* 成员内部类与实例变量具有相同的作用域
*/
class Goo{
int a = 1;
static int b = 2;
class Moo{
int add() {
//成员内部类的优点:可以共享成员变量
return a+b;
}
}
}
把类声明在方法当中(很少见)
package day04;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
public class LocalInnerClassDemo {
//局部内部类
public static void main(String[] args) {
/* final */ int a = 1;
/*
* Foo声明在方法里面,就是一个局部内部类
* 局部内部类的作用域类似于局部变量
*/
class Foo{
int b = 1;
public int add() {
/*
* 局部内部类中可以访问共享外部方法的局部变量
* 但是局部变量必须是final修饰的,jdk1.8之后
* final可以省略,用到就有final
*/
return b+a/*(a++)*/;
}
}
Foo foo = new Foo();
System.out.println(foo.add());
String[] names = {"Jack","Rose","Jerry","Tom","Li"};
//根据字符串的最后一个字符的大小进行排序
class ByLastChar implements
Comparator<String>{
@Override
public int compare(String o1, String o2) {
char lc1 = o1.charAt(o1.length() - 1);
char lc2 = o2.charAt(o2.length() - 1);
return lc1 - lc2;
}
}
Arrays.sort(names, new ByLastChar());
System.out.println(Arrays.toString(names));
}
}
a.匿名内部类非常常见,可以写在任意地方,就是一般的语句
b.语法更像是创建对象 new Comparator(){}
c.匿名类内部类是对原类的一个继承,同时还创建了实例
{}就是继承以后的类体,类体中可以使用所有类的语法
d.匿名内部类中不能写构造器
e.匿名内部类可以从抽象类或者接口中继承、实现
必须提供抽象方法的实例
package day04;
public class AnnInnerClassDemo01 {
public static void main(String[] args) {
// Xoo xoo = new Yoo();
Xoo xoo = new Xoo() {
int a = 1;
@Override
public String toString() {
return "I am Xoo son";
}
};
System.out.println(xoo);
/*
* 匿名内部类
* new Xoo(){}是对Xoo的继承,并且实例化
* new Xoo(){}是Xoo的子类实例,是一个对象
* {}是子类的类体,可以声明大部分类的功能
*/
}
}
class Xoo{
}
//class Yoo extends Xoo{
//
//}
package day04;
public class AnnInnerClassDemo02 {
//从抽象类或者接口中继承、实现的匿名类
public static void main(String[] args) {
/* final */ int a = 1;
Yoo yoo = new Yoo() {
int add() {
return a + 1;
}
};
Koo koo = new Koo() {
@Override
public int add() {
// TODO Auto-generated method stub
return a + 1;
}
};
}
}
abstract class Yoo{
abstract int add();
}
//接口里都是抽象方法
interface Koo{
/* public abstract */ int add();
}
int i = 1;
i.属性 i.方法
8个基本数据类型不能够参与面对对象的开发,因为其不是Object类的子类,所以不能以多态的角度去看待,为此,java为8个基本类型提供了对应的包装类
基本类型 包装类(java.lang)
将基本类型数据自动的转换为包装类实例的过程
包装类实例自动调用xxxValue()方法转换为基本数据类型的过程
MAX_VALUE:获取相对应基本类型的最大值
MIN_VALUE:获取相对应基本类型的最小值
parseXXX(String str):将字符串转换为对应的基本类型数据
java.math.BigInteger
大整型,可以保存的数字比long还大
java.math.BigDecimal
可以做很精确的小数运算,并且可以保存很精确的小数
Bate类 java.util.Date
该类的每一个实例用来描述时间(只能描述、不能操作)
内部维护了一个long值,记录自1970年元旦到这一刻之间的毫秒差
package day02;
import java.util.Date;
public class DateDemo {
/**
* Date在设计上存在两个问题:
* 1.时区
* 2.千年虫(计算机处理时间日期的一个bug)
* @param args
*/
public static void main(String[] args) {
/*
* Date()
* 该构造器创建出来的对象默认表示
* 当前系统时间
*/
Date now = new Date();
System.out.println(now);
/*
* long getTime()
* 获取Date对象秒数的时间距离1970年
* 元旦的毫秒差
*/
long ms = now.getTime();
long hs =System.currentTimeMillis();
System.out.println(ms);
System.out.println(hs);
//计算明天这一刻的毫秒值
ms += 24*60*60*1000;
/*
* 有参构造器Date(long time)
* 创建一个Date对象描述给定毫秒值
* 所表示的时间
*/
Date td = new Date(ms);
System.out.println(td);
/*
* steTime(long time)
* 是当前Date对象表示给定毫秒值
* 所描述的时间
*/
now.setTime(ms);
System.out.println(now);
}
}
SimpleDateFormat类
使用一个特殊的字符串来描述一个时间格式
并使用该时间格式作为桥梁在字符串与Date之间相互转换
Date<->String
y:表示年
yyyy:表示4位的年
yy:表示2位的年
M:表示月
MM:
d:
dd:表示2位是的日期
h:表示小时 12小时制
H:表示小时 24小时制
hh/HH
m:表示分钟
mm:
s:表示秒
ss:表示2位数的秒
E:表示星期
a:表示上下午
在一个时间格式容器中出现的其他字符按照意愿显示:
yyyy-MM-dd hh:mm:ss E a
package day02;
import java.util.Date;
public class DateDemo {
/**
* Date在设计上存在两个问题:
* 1.时区
* 2.千年虫(计算机处理时间日期的一个bug)
* @param args
*/
public static void main(String[] args) {
/*
* Date()
* 该构造器创建出来的对象默认表示
* 当前系统时间
*/
Date now = new Date();
System.out.println(now);
/*
* long getTime()
* 获取Date对象秒数的时间距离1970年
* 元旦的毫秒差
*/
long ms = now.getTime();
long hs =System.currentTimeMillis();
System.out.println(ms);
System.out.println(hs);
//计算明天这一刻的毫秒值
ms += 24*60*60*1000;
/*
* 有参构造器Date(long time)
* 创建一个Date对象描述给定毫秒值
* 所表示的时间
*/
Date td = new Date(ms);
System.out.println(td);
/*
* steTime(long time)
* 是当前Date对象表示给定毫秒值
* 所描述的时间
*/
now.setTime(ms);
System.out.println(now);
}
}
package day02;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatDemo01 {
public static void main(String[] args) {
Date now = new Date();
System.out.println(now);
SimpleDateFormat sdf = new SimpleDateFormat
("yyyy-MM-dd HH:mm:ss E a");
/*
* String format(Date date)
* 将给定的Date对象所描述的时间
* 按照指定的时间格式转换为对应的字符串
*
*/
System.out.println(sdf);
String str = sdf.format(now);
System.out.println(str);
}
}
package day02;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class SimpleDateFormatDemo02 {
public static void main(String[] args) throws ParseException {
String str = "2022-05-25 15:37:56";
SimpleDateFormat sdf =
new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
/*
* Date parse(String str)
* 将给定的字符串按照给定的日期格式
* 解析为对应的Date对象
*/
Date date = sdf.parse(str);
System.out.println(date);
}
}
package day02;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
public class SimpleDateFormatDemo03 {
/**
* 控制台输入你的生日(yyyy-MM-dd)
* 计算到今天为止你一共活了多少天
* @throws ParseException
*/
public static void main(String[] args) throws ParseException {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入你的生日(yyyy-MM-dd)");
String birStr = scanner.nextLine();
SimpleDateFormat sdf =
new SimpleDateFormat("yyyy-MM-dd");
Date birDate = sdf.parse(birStr);
Date now = new Date();
long time = now.getTime() - birDate.getTime();
System.out.println(time/1000/60/60/24/360);
}
}
该类是SimpleDateFormat的父类
该类可以根据给定的地区将Date转换为字符串
不同的地区对应的时间格式字符串是预定义的
package day02;
import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
public class DateFormatDemo {
public static void main(String[] args) {
Date now =new Date();
System.out.println(now);
/*
* 创建DateFormat的实例需要使用其
* 自身提供的工厂方法
* getDateInstance()
*/
DateFormat df =
DateFormat.getDateInstance(DateFormat.FULL,Locale.JAPAN );
/*
* style:打印的时间样式,DateFormat类中提供了常量
* aLocale:地区
*/
String str = df.format(now);
System.out.println(str);
}
}
日历类,用来操作时间的类
Calendar是一个抽象类,不能直接实例化
使用其提供的工厂方法获取实例:getInstance()
该方法会根据当前系统所在的地区自动判定应该
使用哪个子类来实现
package day02;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
public class CalendarDemo01 {
public static void main(String[] args) {
//通过工厂方法来获取实例
Calendar calendar =
Calendar.getInstance();
//格林高丽历法(阳历)
// Calendar calendar2 =
// new GregorianCalendar();
//默认条件下创建的Calendar对象表示的是当前的系统时间
System.out.println(calendar);
/*
* 查看calendar时间,通过输出该对象得到
* 的字符串不友好,可以先将Calendar转换
* 为Date
* Date getTime()
* 该方法的作用是将当前Calendar描述的时间
* 转换为一个Date对象并返回
*/
Date date = calendar.getTime();
System.out.println(date);
/*
* void setTime()
* 是当前Calendar描述给定Date对象所描述的时间
*/
Date now = new Date();
calendar.setTime(now);
System.out.println(calendar);
}
}
package day02;
import java.util.Calendar;
public class CalenderDemo02 {
//获取某个时间单位的值
public static void main(String[] args) {
Calendar calendar =
Calendar.getInstance();
System.out.println(calendar);
/*
* int get(int field)
* field该参数对应Calendar提供的若干常量
* 每一个常量表示一个不同的时间单位
*
*/
//获取年份
int year =calendar.get(Calendar.YEAR);
System.out.println(year);
//获取月份 月份从0开始,0表示1月
int month = calendar.get(Calendar.MONTH);
System.out.println(month + 1);
/*
* 对于天而言有以下几种时间分量:
* Calender.DATE 几号
* Calender.DAY_OF_MONTH 月中天
* Calender.DAY_OF_WEEK 周中天
* Calender.DAY_OF_YEAR 年中天
*/
int day = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(day);
int dow = calendar.get(Calendar.DAY_OF_WEEK);
/*
* 对于星期而言符合美国习惯
* 周日为一周的第一天
*/
System.out.println("星期"+(dow==1?7:(dow-1)));
int td = calendar.get(Calendar.WEEK_OF_MONTH);
System.out.println(td);
}
}
package day02;
import java.util.Calendar;
public class CalenderDemo03 {
//给某个时间单位设置值
public static void main(String[] args) {
Calendar calendar =
Calendar.getInstance();
/*
* void set(int field,int value)
* 设置当前Calender指定时间分量的值
*/
//设置年份2008年
calendar.set(Calendar.YEAR, 2008);
//设置月份9月,月份从0开始算起
//calendar.set(Calendar.MONTH, 8);
calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);
//设置为8号
//calendar.set(Calendar.DAY_OF_MONTH, 8);
/*
* 当给定的时间分量对应的值超出了
* 当前时间分量所允许的最大值时
* 会自动进位
*/
calendar.set(Calendar.DAY_OF_MONTH, 31);
System.out.println(calendar.getTime());
}
}
package day02;
import java.util.Calendar;
public class CalenderDemo02 {
//获取某个时间单位的值
public static void main(String[] args) {
Calendar calendar =
Calendar.getInstance();
System.out.println(calendar);
/*
* int get(int field)
* field该参数对应Calendar提供的若干常量
* 每一个常量表示一个不同的时间单位
*
*/
//获取年份
int year =calendar.get(Calendar.YEAR);
System.out.println(year);
//获取月份 月份从0开始,0表示1月
int month = calendar.get(Calendar.MONTH);
System.out.println(month + 1);
/*
* 对于天而言有以下几种时间分量:
* Calender.DATE 几号
* Calender.DAY_OF_MONTH 月中天
* Calender.DAY_OF_WEEK 周中天
* Calender.DAY_OF_YEAR 年中天
*/
int day = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(day);
int dow = calendar.get(Calendar.DAY_OF_WEEK);
/*
* 对于星期而言符合美国习惯
* 周日为一周的第一天
*/
System.out.println("星期"+(dow==1?7:(dow-1)));
int td = calendar.get(Calendar.WEEK_OF_MONTH);
System.out.println(td);
}
}
package day02;
import java.util.Calendar;
public class CalenderDemo03 {
//给某个时间单位设置值
public static void main(String[] args) {
Calendar calendar =
Calendar.getInstance();
/*
* void set(int field,int value)
* 设置当前Calender指定时间分量的值
*/
//设置年份2008年
calendar.set(Calendar.YEAR, 2008);
//设置月份9月,月份从0开始算起
//calendar.set(Calendar.MONTH, 8);
calendar.set(Calendar.MONTH, Calendar.SEPTEMBER);
//设置为8号
//calendar.set(Calendar.DAY_OF_MONTH, 8);
/*
* 当给定的时间分量对应的值超出了
* 当前时间分量所允许的最大值时
* 会自动进位
*/
calendar.set(Calendar.DAY_OF_MONTH, 31);
System.out.println(calendar.getTime());
}
}
package day02;
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class CalendarDemo04 {
//计算时间
public static void main(String[] args) {
//计算该月月底:下个月的1号减去1天
Calendar calendar =
Calendar.getInstance();
System.out.println(calendar.getTime());
/*
* void add(int field,int value)
* 将给定的时间分量累加给定的值
*/
calendar.add(Calendar.MONTH, 1);
System.out.println(calendar.getTime());
calendar.set(Calendar.DAY_OF_MONTH, 1);
System.out.println(calendar.getTime());
//将日期向前推一天
calendar.add(Calendar.DAY_OF_MONTH, -1);
System.out.println(calendar.getTime());
SimpleDateFormat sdf =
new SimpleDateFormat("yyyy-MM-dd E");
System.out.println(sdf.format(calendar.getTime()));
}
}
package day02;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Scanner;
public class CalendarDemo05 {
/**
* 计算商品的促销日期:
* 1.控制台输入商品的生产日期(yyyy-MM-dd)
* 2.控制台输入商品的保质期天数
* 3.计算促销时间:
* 是商品到期日的那一个星期的前两个星期的星期三
* @throws ParseException
*
*/
public static void main(String[] args) throws ParseException {
Scanner scanner =new Scanner(System.in);
System.out.println("请输入商品的生产");
String dateStr = scanner.nextLine();
Scanner scanner2 = new Scanner(System.in);
System.out.println("请输入保质期天数:");
int days = scanner2.nextInt();
//将商品的生产日期转换为Date
SimpleDateFormat sdf =
new SimpleDateFormat("yyyy-MM-dd");
Date date = sdf.parse(dateStr);
//再将date转换为Calendar
Calendar calendar = Calendar.getInstance();
calendar.setTime(date);
//求出商品的到期日
calendar.add(Calendar.DAY_OF_YEAR, days);
//向前推两周(向前推14天)
// calendar.add(Calendar.WEEK_OF_YEAR, -2);
calendar.add(Calendar.DAY_OF_YEAR, -14);
//将日期设置为周三
calendar.set(Calendar.DAY_OF_WEEK, 4);
//将Calendar类型的日期转换为Date
date = calendar.getTime();
//再将Date类型的促销日期转换为String
System.out.println("促销日期:"+sdf.format(date));
}
}
String->SinmpleDateFomrat.parse()->Date
Date->Calendar.setTime()->Calendar
Calendar->Calendar.getTime()->Date
Date->SimpleDateFormat.format()->String
Calendar操作时间的方式:
Java中的集合框架
不区分类型
Collection接口:该接口是所有集合的超类(父接口)
Collection接口又派生出两个子接口
Set集合:不重复集、无序集(没有下标)
List集合:可重复集、有序集
所谓的不重复:指的是Set集合里面不能出现两个equals()比较为true的元素
注意:数组不属于集合的范畴
Iterator inerator()
package day04;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
public class InteratorDemo01 {
/**
* 遍历集合元素有一种通用方式:迭代器模式
*/
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("one");
c.add("#");
c.add("two");
c.add("#");
c.add("three");
c.add("#");
c.add(null);
System.out.println(c);
/*
* Iterator是一个接口
* 不同的集合返回的迭代器实现不尽相同
*/
Iterator it = c.iterator();
System.out.println(it);
/*
* 注意:
* 使用迭代器遍历集合的顺序必须遵循:
* 问取删(删除并不是必须的)
* 问:boolean hasNext()
* 该方法的作用是查看当前集合中是否还有元素可以遍历
* 取:Object next()
* 从集合中取出一个元素
* 删:void remove()
* 删除通过next()方法遍历出来的元素
*/
while (it.hasNext()) {
Object obj = (Object) it.next();
// if ("#".equals(obj)) {
// it.remove();
// }
//remove()方法在每一次调用next()方法之后只能调用一次
// it.remove();
//迭代器遍历集合有一个要求:
//在迭代过程中不允许通过集合增删元素
// c.remove(obj);
System.out.println(obj);
}
System.out.println(c);
}
}
package day04;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorDemo02 {
public static void main(String[] args) {
int i =1;
double d = i;
int a = (int)d;
List<String> list =
new ArrayList<String>();
list.add(" one ");
list.add(" two ");
list.add(" three ");
Iterator<String>/*泛型去掉获取的就是Object*/ it =list.iterator();
while (it.hasNext()) {
String string = it.next();
System.out.println(string.trim());
}
}
}
ArrayList在Java1.2版本以后采用了变长数组算法实现
线程不安全,效率高速度快
Vector咋Java1.0版本,底层也是采用变长算法实现的,
线程安全,效率比较低,实现了List接口,但是不常用
ArrayList是采用变长数组算法实现的,更适合查询数据
LinkedList是采用双向链表结构实现的,更适合频繁的增删操作
List集合:可重复集、有序集 List也是接口
List接口的实现类:
ArrayList:内部使用数组实现
LinkedList:内部使用链表实现
Vector:不常用
add()
remove()
int indexOf()
泛指的某一种类型
jdk1.5之后推出的新特性
package day04;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Demo01 {
/**
* 集合支持泛型
* 泛型指定的是集合中的元素类型
*/
public static void main(String[] args) {
List<String> c1 =
new ArrayList<String>();
c1.add(" one ");
c1.add(" two ");
c1.add(" three ");
System.out.println(c1);
for (int i = 0; i < c1.size(); i++) {
System.out.println(c1.get(i));
}
List c2 = new ArrayList();
c2.add(" one ");
c2.add(" two ");
c2.add(" three ");
System.out.println(c2);
//遍历c2集合,同时将c2集合左右两边的空白去掉
for (int i = 0; i < c2.size(); i++) {
System.out.println(((String)c2.get(i)).trim());
}
List l = c1;
l.add(4);
System.out.println(l);
for (int i = 0; i < c1.size(); i++) {
System.out.println(c1.get(i));
}
}
}
增强for循环(for each) java1.5之后推出的新特性
语法:
for(元素类型 e:集合或数组){
循环体;
}
新循环有别于传统循环,其出现的目的是简化遍历集合或者遍历数组的
package day04;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ForEachDemo {
public static void main(String[] args) {
String[] ary = {"a","b","c","d","e"};
//
for (int i = 0; i < ary.length; i++) {
System.out.println(ary[i]);
}
//新循环
for(String str:ary) {
System.out.println(str);
}
List<String> list =
new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
//传统方式
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
//迭代器方式
Iterator<String> it =
list.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//新循环方式
for (String s : list) {
System.out.println(s);
list.remove(s);
//java.util.ConcurrentModificationException
}
/*
* 新循环就是使用迭代器来实现的
* java在编译的时候,会将新循环转换为迭代器
* 的方式,那么在使用新循环遍历集合时
* 不允许通过集合来增删元素
*/
}
}
Queue(接口)
队列也是用来保存一组数据的,但是有别于数组和集合
队列存取元素必须遵循先进先出的原则(FIFO)
LinkedList具有存取效率高的特点,所以java使用该类
作为队列的实现类来使用
队列的遍历是一次性的,想要获取队列中的某个元素,
就必须将队列中该元素之前所有的元素取出后才能使用和访问。
队列的相关方法:
boolean offer(E e)
向队列的末尾追加新元素(入队)
E poll()
获取并从队列中删除队首元素(出队)
E peek()
仅获取队首元素,但不将其从队列中删除
package day04;
import java.util.LinkedList;
import java.util.Queue;
public class QueueDemo {
//队列:先进先出(FIFO)
public static void main(String[] args) {
Queue<String> queue =
new LinkedList<String>();
queue.offer("one");
queue.offer("two");
queue.offer(null);
queue.offer("three");
queue.offer("four");
// System.out.println(queue.size());
// System.out.println(queue);
// System.out.println(queue.peek());
// System.out.println(queue.peek());
// System.out.println(queue.poll());
/*
* E poll()
* 如果队列中不包含任何元素,poll()
* 方法就会返回null
*/
//遍历队列
// for (int i = 0; i < queue.size(); i++) {
// System.out.println(queue.poll());
// }
//倒着循环
// for (int i = queue.size(); i > 0; i--) {
// System.out.println(queue.poll());
// }
// System.out.println(queue.poll());
// String str = null;
// while ((str = queue.poll())!= null) {
// System.out.println(str);
// }
//有小问题
//新循环
for (String str : queue) {
System.out.println(str);
}
System.out.println(queue);
}
}
所谓的双端队列:队列的两端都可以出队入队
当我们使用双端队列存储元素时,只从一侧操作时,
就形成了一种存储模式:先进后出,就形成了经典的数据结构:栈
使用栈是为了让操作具有可追溯性,
通常我们实现某个操作有后退功能时,常使用栈
package day04;
import java.rmi.activation.Activatable;
import java.util.Deque;
import java.util.LinkedList;
public class DequeDemo {
/**
* 双端队列:该队列的两端都可以出队入队
* 当我们只从一段操作时,就实现了经典的
* 数据结构:栈(FILO)
*/
public static void main(String[] args) {
Deque<String> stack =
new LinkedList<String>();
/*
* void push(E e)
* 向栈中"压入"元素(入栈操作)
*
*/
stack.push("one");
stack.push("two");
stack.push("three");
stack.push("four");
System.out.println(stack.size());
System.out.println(stack);
//peek()获取"栈顶"元素(但不删除)
System.out.println(stack.peek());
/*
* E pop()
* 获取栈顶元素,当获取栈顶元素时,该元素
* 从栈中被移除
* 注意:当栈中不包含元素时,该方法会抛出异常
*
*/
for (int i = stack.size(); i > 0; i--) {
System.out.println(stack.pop());
}
System.out.println(stack);
System.out.println(stack.pop());//java.util.NoSuchElementException
}
}
该接口的实现类是可比较的
实现该接口必须重写其中的一个方法:
public interface Comparable {
public int compareTo(T t);
}
compareTo方法的返回值:
返回的整数不关心具体值的大小,关心的是取值范围
当返回值>0时,当前对象比给定的对象大
反之一样
当返回值=0时,当前对象和给定对象相等
用于定义临时的比较规则,不是默认规则
package day04;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SortDemo02 {
public static void main(String[] args) {
List<String> list =
new ArrayList<String>();
list.add("haosjajd");
list.add("dishfj");
list.add("jsiyeuhhuh");
list.add("sjf");
list.add("skfssjf");
list.add("a");
list.add("as");
list.add("ahks");
System.out.println(list);
// Collections.sort(list);
Collections.sort(list, new MyComparator());
System.out.println(list);
}
}
class MyComparator implements
Comparator<String>{
@Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
}
无序集、不重复集(Set集合中不会出现两个equals()比较为true的元素)
TreeSet:使用二叉树实现(不常用)
HashSet:使用散列算法实现
package day05;
import java.util.HashSet;
import java.util.Set;
public class SetDemo01 {
//Set集合:无序、不重复
public static void main(String[] args) {
Set<String> set =
new HashSet<String>();
set.add("one");
set.add("two");
set.add("three");
set.add("four");
System.out.println(set.size());
/*
* 元素的添加顺序和集合内部元素的存储顺序是不一致的,和hash值有关
*/
System.out.println(set);
//Set集合不能存入重复的元素
set.add("three");
}
}
package day05;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class SetDemo02 {
//遍历集合
public static void main(String[] args) {
Set<String> set =
new HashSet<String>();
set.add("one");
set.add("two");
set.add("three");
set.add("four");
//迭代器方式
Iterator<String> iter = set.iterator();
while (iter.hasNext()) {
String str = (String) iter.next();
System.out.println(str);
}
//新循环方式
for (String str : set) {
System.out.println(str);
}
}
}
对于HashSet而言,它存取元素时依赖于元素的hashCode()方法,
hashCode()方法是Object定义的方法,所有的类都具备该方法,通常我们重写一个Equals()方法时就要求连同重写hashCode()方法
Map:散列表 是一个多行两列的表格,每一行存储一项
一项包含两个部分:key-value(键值对)
其常见的实现类:HashMap(使用散列算法实现的Map)
散列表:Map(key-value)
容量:散列表中的散列表数组的大小(不能无限大)
散列运算:根据key计算散列值(hash值)的算法(散列算法)
散列桶:散列值相同元素的“线性集合”
加载因子:散列数值的加载率,一般小于75%性能就比较理想
(元素数量/散列数组的大小)
散列查找:根据key计算散列值,根据散列值的下标查找value
散列表中的key不同,value可以相同
加载因子的比值如果超过0.75时,散列数组将扩容,存入于原数组中的数据,要重新进行散列运算后存入新的数组,并不是简单的将原数组中的数据复制到新数组当中,这个过程称为rehash(重新散列),那么扩容数组,rehash会带来一定的性能开销
1)key可以是任意对象,value也可以是任意对象
2)key-value成对放置在集合当中
3)重复的key算一个,重复添加时是替换value操作
4)根据key的散列值计算散列表,元素按照散列值排序
5)HashMap默认容量是16,默认的加载因子是0.75
6)HashMap可以根据key检索查找value的值
7)HashMap可以在构造器中指定参数:初始容量和加载因子
V put(K k,V v)
将一组键值对key-value存入到Map中,因为Map要求key不允许重复,所以若使用相同的key存入不同的元素,是替换value操作,put方法的返回值是被替换的value