包的概述:
其实就是文件夹作用:对类进行分类管理包的划分:举例:学生的增加,删除,修改,查询老师的增加,删除,修改,查询以及以后可能出现的其他的类的增加,删除,修改,查询
包的定义及注意事项:
定义包的格式package 包名 ;多级包用 . 分开即可注意事项:package 语句必须是程序的第一条可执行的代码package 语句在一个 java 文件中只能有一个如果没有 package ,默认表示无包名
带包的类的编译和运行:
手动式a:javac 编译当前类文件。b: 手动建立包对应的文件夹。c: 把 a 步骤的 class 文件放到 b 步骤的最终文件夹下。d: 通过 java 命令执行。注意了:需要带包名称的执行java com.qianfeng.HelloWorld自动式a:javac 编译的时候带上 -d 即可javac -d . HelloWorld.javab: 通过 java 命令执行。和手动式一样
不同包下类之间的访问:导包
导包概述不同包下的类之间的访问,我们发现,每次使用不同包下的类的时候,都需要加包的全路径。比较麻烦。这个时候, java 就提供了导包的功能。导包格式import 包名 ;注意:这种方式导入是到类的名称。虽然可以最后写 * ,但是不建议
权限修饰符:
本类 | 同包 | 非同包子类 | 非同包其他类 | |
private |
√
| |||
默认 |
√
|
√
| ||
protected |
√
|
√
|
√
| |
public |
√
|
√
|
√
|
√
|
类及其组成可以用的修饰符:
类:默认, public , fifinal , abstract我们自己定义: public 居多成员变量:四种权限修饰符均可 ,fifinal,static我们自己定义: private 居多构造方法:四种权限修饰符均可 , 其他不可我们自己定义: public 居多 成员方法:四种权限修饰符均可, fifianl,static,abstract我们自己定义: public 居多
方法形式参数:类,具体类或者抽象类 接口以及返回值问题(具体类/抽象类/接口类型)
方法的形式参数:
基本类型: (形式参数的改变不影响实际参数),要什么基本类型,实际参数直接传递具体的数据值 (比如int)
引用类型: 方法的形式参数是具体类,调用该方法,实际参数需要传递这个具体类的对象;
代码体现:
class Student{
public void study(){
System.out.println("学习JavaEE之JavaSE基础");
}
}
class StudentDemo{
public void method(Student student){//形式参数一个引用类型:具体类,调用该方法,实际参数需要一个学生对象
student.study() ;
}
}
//测试类
public class ArgsDemo1 {
public static void main(String[] args) {
//调用StudentDemo类的method方法
//创建StudentDemo类对象
StudentDemo sd = new StudentDemo() ;
//调用该方法,实际参数需要一个学生对象
Student s = new Student() ;
sd.method(s); //实际参数s
}
}
引用类型: 形式参数是抽象类,调用该方法,实际参数需要传递该抽象类的具体的子类对象,抽象类多态;
代码体现:
abstract class Person{//人类
public abstract void work(); //工作
}
class PersonDemo{
//成员方法
public void show(Person p){//形式参数是一个抽象类,抽象类不能实例化,需要new 它的子类对象 抽象类多态
p.work() ;
}
}
//只能现在提供抽象类的具体的子类
class Worker extends Person{
@Override
public void work() {
System.out.println("爱生活,爱工作,爱高圆圆");
}
}
//测试类
public class ArgsDemo2 {
public static void main(String[] args) {
//要访问PersonDemo类里面的show方法
PersonDemo pd = new PersonDemo() ;
//创建Person对象
//Person p = new Person();
// pd.show(p);
//抽象类多态
Person p = new Worker() ;
pd.show(p);
System.out.println("-----------------------------------------");
//匿名对象
pd.show(new Worker());
}
}
引用类型: 方法的形式参数是接口,调用该方法,实际参数需要传递该接口的子实现类对象,接口多态;
代码体现:
interface Love{
void love() ;
}
class LoveDemo{
public void function(Love lo){ //方法形式参数是一个接口类型,接口new不了
lo.love();
}
}
//需要提供具体的子实现类
class LoveImpl implements Love{
@Override
public void love() {
System.out.println("love loveImpl...");
}
}
//测试类
public class ArgsDemo3 {
public static void main(String[] args) {
//调用LoveDemo类的中的function方法
//创建LoveDemo类对象
LoveDemo ld = new LoveDemo() ;
//创建Love对象
//Love love = new Love() ;//接口不能实例化,肯定需要接口的子实现类
//ld.function(love);
//接口多态的方式:接口名 对象名 = new 具体的子实现类名() ;
Love love = new LoveImpl() ;
ld.function(love);
}
}
方法的返回值问题:
返回基本类型: 返回int--->谁调用这个方法,调用者必须使用int类型接收
返回引用类型: 方法的返回值,返回的是一种具体类型的情况,一定要返回当前这个具体的类的对象
代码体现:
class Demo{
public int getMax(int a,int b){//方法的返回值是基本类型
if(a>b){
return a;
}else{
return b ;
}
}
}
//学生类
class Student{
public void study(){
System.out.println("正在学习JavaEE");
}
}
//StudentDemo
class StudentDemo{
public Student method(){//这个的返回值是一个引用类型,具体类---方法结束,必须返回一个当前类的具体类对象
// 如何结束???
//return Student;
//方式1 :
/*Student s = new Student() ;
return s;*/
//方式2:匿名对象的格式
return new Student() ;
}
}
//测试
public class ReturnDemo1 {
public static void main(String[] args) {
//调用Demo类的getMax方法
Demo demo = new Demo() ;
int result = demo.getMax(10,20) ; //调用者
System.out.println(result);
System.out.println("---------------------------------------------") ;
//调用StudentDemo这个类里面的method方法
StudentDemo sd = new StudentDemo() ;
Student s = sd.method(); // 这个方法的本质: new Student();
s.study() ;
}
}
返回引用类型:方法的返回值是一种抽象类的情况,必须返回抽象类的子类,抽象类多态
代码体现:
abstract class Person{
public abstract void work();
}
class PersonDemo {
public Person show(){ //方法的返回值是一个抽象类,必须要提供抽象类子类
//??
/* Person p = new Person() ;//抽象类不能new
return p ;*/
//return new Person() ;
//需要抽象类的子类对象:抽象类多态
//方式1:抽象类多态
/* Person p = new Programmer() ;
return p;*/
//方式2:匿名对象
return new Programmer() ;
}
}
//定要一个子类:抽象类的子类
class Programmer extends Person{
@Override
public void work() {
System.out.println("不断的去完成项目开发...");
}
}
//测试类
public class ReturnDemo2 {
public static void main(String[] args) {
//调用PersonDemo的show方法
PersonDemo pd = new PersonDemo() ;
Person person = pd.show(); //show方法本质 new Programmer() ;
person.work();
}
}
返回引用类型:方法的返回值是一个接口的情况,必须返回接口的子实现类;接口多态;
代码体现:
interface Mary{
void mary() ;
}
//定义一个类
class MaryDemo{
public Mary method(){ //方法的返回值是接口类型,接口实例化不了的!
//??
//Mary mary = new Mary() ;
// return mary ;
//return new Mary() ;
//方式1:接口多态
// Mary mary = new WeddingCompany() ;
//return mary ;
//方式2:匿名对象
return new WeddingCompany() ;
}
}
//需要接口的子实现类
//婚庆公司
class WeddingCompany implements Mary{
@Override
public void mary() {
System.out.println("婚庆公司布置婚礼现场!");
}
}
//测试类
public class ReturnDemo3 {
public static void main(String[] args) {
//调用MaryDemo类名的method方法
MaryDemo maryDemo = new MaryDemo() ;
Mary m = maryDemo.method();//method方法本质:创建子实现类对象 new WeddingCompany() ;
m.mary();
}
}
内部类
内部类概述:
把类定义在其他类的内部,这个类就被称为内部类。举例:在类 A 中定义了一个类 B ,类 B 就是内部类。内部类的访问特点:内部类可以直接访问外部类的成员,包括私有。外部类要访问内部类的成员,必须创建对象。
成员内部的常见修饰符private 为了保证数据的安全性static 为了让数据访问更方便被静态修饰的成员内部类只能访问外部类的静态成员内部类被静态修饰后的方法可以是静态方法,也可以是非静态方法
外部类名.内部类名 对象名 = new 外部类名(). new 内部类类名() ;
class Outer2{
private int num = 100 ; //Outer2类的里面的成员变量
//成员内部类:看成Outer2的成员
class Inner2{
//成员方法show
public void show(){
System.out.println(num) ;
}
}
//外部类的成员方法
public void method(){
//想去访问Inner2了中的show()?
//show(); //说明 show方法Outer2类的成员方法
//通过内部类对象来访问
Inner2 inner2 = new Inner2() ;
inner2.show();
}
}
//测试类
public class InnerClassDemo2 {
public static void main(String[] args) {
//测试类中:去访问外部类的成员方法
Outer2 outer2 = new Outer2();
outer2.method();
System.out.println("-----------------------------------------");
//如何直接通过外部类访问内部类的成员方法?
//外部类名.内部类名 对象名 = new 外部类名(). new 内部类类名() ;
Outer2.Inner2 oi = new Outer2().new Inner2() ;
oi.show() ;
}
}
成员内部类(静态):
1:非静态的成员内部类,成员只能是非静态的。2:内部类被静态修饰后的方法有静态和非静态之分。他们的访问和不用静态是不一样的。访问非静态方法:外部类名.内部类名 对象名 = new 外部类名.内部类名();访问静态方法:上面创建的对象访问,或者外部类名.内部类名.方法名();
被静态修饰的成员内部类:这个成员内部类的中的所有的方法:静态的还是非静态的,访问外部类的成员必须只能访问静态的东西
静态的成员内部类:外部类直接访问静态内部类的成员,
` 将静态的成员内部类看成是外部类的静态成员
外部类名.内部类名 对象名 = new 外部类名.内部类名();
代码体现:
class Outer3{
private int num = 20 ;
private static int num2 = 50 ;
//静态的成员内部类
static class Inner3{
//非静态的方法
public void show(){
//System.out.println(num);
System.out.println(num2) ;
}
//静态的方法
public static void show2(){
//System.out.println(num);
System.out.println(num2);
}
}
}
//测试类
public class InnerClassDemo3 {
public static void main(String[] args) {
//要访问静态的成员内部类中的成员方法以及静态方法?
//外部类名.内部类名 对象名 = 外部类对象.内部类对象; //这个格式针对成员内部类非静态
// Outer3.Inner3 oi = new Outer3().new Inner3() ;
//外部类名.内部类名 对象名 = new 外部类名.内部类名();
Outer3.Inner3 oi = new Outer3.Inner3();
oi.show(); //show() 静态成员内部类的非静态的方法: 必须对象来访问
oi.show2() ;//show2():静态方法:不推荐 对象名访问访问
//静态东西:使用类名访问
System.out.println("-------------------------------------------") ;
//Inner3类看成是Outer3静态成员,show2()在Inner3也是静态的方法
Outer3.Inner3.show2() ;
}
}
局部内部类:在外部类的局部位置,方法定义中
特点:
不管是局部内部类/成员内部类: 里面的成员都可以直接访问外部类的成员包括私有
如果通过外部类直接访问局部内部类的成员?
在局部位置上,创建了局部内部类的对象,对象名调用成员方法
代码体现:
class Outer{
private int x = 100 ;
//外部类的成员方法
public void show(){
int num = 20 ; //隐藏了final修饰符
//局部内部类
class Inner{
//成员方法
public void method(){
System.out.println(x);//局部内部类的成员在访问外部类的成员
System.out.println(num) ; //此时这里面需要访问的外部类的局部变量num
}
}
//创建局部内部类对象
Inner inner = new Inner() ;
inner.method();
}
}
//测试类
public class InnerClassDemo {
public static void main(String[] args) {
//就创建外部类的对象
Outer outer = new Outer() ;
outer.show();
}
}
匿名内部类:(没有名字的类)
格式:
抽象类或者接口的匿名内部类
new 类名或者是接口名(){ //类:一般都是抽象类 ,具体类也可也,但是不推荐
重写方法() {
...
}
};
场景范围:
就是在方法的形式参数以及返回值是抽象类或者接口的情况下,是一种简化格式
匿名内部类的本质: 就是继承该类(抽象类)或者实现了给接口的子类对象;
代码体现:
interface Love{
void show() ;
void show2() ;
}
/*
class LoveImpl implements Love{ //类名 LoveImpl
@Override
public void show() {
}
@Override
public void show2() {
}
}
*/
//外部类
class Outer2{
public void method(){
//没有使用匿名内部类之前
/* class Inner2{
public void show(){
System.out.println("show Inner...");
}
public void show2(){
System.out.println("show2 Inner... ");
}
}
//创建Inner对象
Inner2 inner = new Inner2() ;
inner.show();
inner.show2() ;*/
/*
new 类名或者是接口名(){
* 重写方法() {
...
}
};
*/
//匿名内部类格式:简化书写格式
/* new Love(){
@Override
public void show() {
System.out.println("show Love");
}
@Override
public void show2() {
System.out.println("show2 Love");
}
}.show();
new Love(){
@Override
public void show() {
System.out.println("show Love");
}
@Override
public void show2() {
System.out.println("show2 Love");
}
}.show2();*/
//上面这个格式在访问方法上面比较麻烦
//优化:
//给匿名内部类 new 类名或者接口名(){...重写方法} 起一个对象名字
Love l = new Love(){
@Override
public void show() {
System.out.println("show Love");
}
@Override
public void show2() {
System.out.println("show2 Love");
}
} ;
l.show();
l.show2();
}
}
//测试类
public class NoClassDemo {
public static void main(String[] args) {
Outer2 outer2 = new Outer2() ;
outer2.method();
}
}
匿名内部类在开发中的使用情况:
抽象类,作为形式参数,代码体现:
abstract class Person{
public abstract void work() ;//工作
}
class PersonDemo{
public void method(Person p){ //抽象类 作为形式参数,抽象类不能实例化
p.work();
}
}
//定义子类 继承自Person类,重写work
/*class Worker extends Person{
@Override
public void work() {
System.out.println("日日夜夜敲代码...");
}
}*/
//测试类
public class Test {
public static void main(String[] args) {
//调用PersonDemo类的method 方法
/* PersonDemo pd = new PersonDemo() ;
//抽象类多态:
Person p = new Worker() ;
pd.method(p)*/; // ---->p.work();
//方式2:匿名内部类
PersonDemo pd = new PersonDemo() ;
// new 抽象类名或者接口名(){
// *
// * 重写抽象方法...
// * } ;
pd.method(new Person(){
@Override
public void work() {
System.out.println("日日夜夜敲代码");
}
});
}
}
接口:作为形式参数,代码体现
interface Fly{
void fly() ;
}
class FlyDemo{
public void method(Fly fly){//方法的形式参数是一个接口,调用方法,需要接口的子实现类对象
fly.fly();
}
}
//定义一个子实现类 实现Fly接口
class Bird implements Fly{
@Override
public void fly() {
System.out.println("鸟会飞了...");
}
//测试列
public class Test2 {
public static void main(String[] args) {
//调用FlyDemo类的method方法
FlyDemo fd = new FlyDemo() ;
//接口多态
Fly fly = new Bird() ;
fd.method(fly); //----->fly.fly();
System.out.println("------------------------------------------");
//直接 匿名内部类
/**
* new 类名或者接口名(){
* 重写方法
* } ;
*/
FlyDemo fd2 = new FlyDemo() ;
fd2.method(new Fly(){
@Override
public void fly() {
System.out.println("会飞了...");
}
});
}
}
方法的返回值是抽象类型,方法结束,需要返回抽象类的子类对象
代码体现:
abstract class Person2{
public abstract void work() ;
}
class CodeDemo{
public Person2 show(){
//需要返回抽象类的子类对象
//抽象类多态
/*Person2 p = new Programmer() ;
return p;*/
//使用抽象类的匿名内部类的格式
return new Person2(){
@Override
public void work() {
System.out.println("程序员日日夜夜开发项目");
}
} ;
}
}
//定义一个子类
class Programmer extends Person2{
@Override
public void work() {
System.out.println("程序员不断开发新的项目");
}
}
//测试类
public class Test3 {
public static void main(String[] args) {
//调用CodeDemo的show
/* CodeDemo cd = new CodeDemo() ;
Person2 p = cd.show() ;//---本质:new Programmer() ;
p.work();*/
CodeDemo cd2 = new CodeDemo() ;
Person2 person2 = cd2.show();
person2.work();
}
}
方法的返回值如果是接口类型,方法结束,必须返回接口的子实现类对象
代码体现:
interface CanCry{
void cry() ; //吼叫的方法
}
class CryDemo{
public CanCry funtion(){
//返回接口的子实现类对象
//接口多态
/* CanCry canCry = new Cat();
return canCry ;*/
//接口匿名内部类
return new CanCry() {
@Override
public void cry() {
System.out.println("狗发出汪汪汪的吼叫");
}
} ;
}
}
//定义CanCry接口的子实现类实现cry方法
class Cat implements CanCry{
@Override
public void cry() {
System.out.println("猫发出喵喵的吼叫");
}
}
//测试类
public class Test4 {
public static void main(String[] args) {
//调用CryDemo的function方法
/* CryDemo cd = new CryDemo() ;
CanCry cc = cd.funtion() ; //本质---->new Cat() ;
cc.cry();*/
CryDemo cd2 = new CryDemo() ;
CanCry cc = cd2.funtion() ; //本质--->接口的匿名内部类--->代表任意子实现类对象
cc.cry();
}
}
常用类
概述:
Object 类是所有类的根类 , 所有类的超类也就是父类
public String toString():本身的含义 :返回对象的字符串表示形式(直接输出对象的名称,就是地址值)
结果应该是一个简明扼要的表达,容易让人阅读。 建议所有子类覆盖此方法
public class ObjectDemo {
public static void main(String[] args) {
//创建一个学生
Student s = new Student("高圆圆",43,"女") ;
//直接对象名称,直接默认访问的就是Object类的toString()---->打印出来的地址值
System.out.println(s) ;//com.qf.object_03.Student@1540e19d 直接输出对象名:地址值 没有意义
System.out.println(s.toString());
//重写Object的toString()---->显示让人容易读懂的信息表达式 ---这个事物的具体信息
}
}
//学生类
public class Student extends Object{ //默认继承Object 隐藏了extends Object:不用写
private String name ;//姓名
private int age ;//年龄
private String gender ;//性别
//无参
public Student() {
}
//有参
public Student(String name, int age,String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
//setXXX()/getXXX()
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
//自己手动方式重写Object类的toString
/* @Override
public String toString() {
return "学生的姓名是"+name+",年龄是:"+age+",性别是,"+gender ;
}*/
//idea自动生成
//alt+fn+ins--->属性全选--->ok
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
Object类的常用功能:
public final Class getClass():使用对象名调用getClass():获取正在运行的类或者接口(字节码文件对象)
也称为"Class类对象"
public int hashCode() (了解:哈希算法---提供哈希表) 返回对象的哈希码值 (理解为 "地址值",不是实际意义的地址值)
每一个对象的哈希码值不同的
public class ObjectDemo2 {
public static void main(String[] args) {
Student s1 = new Student() ;
System.out.println(s1);//s1.toString()
//toString()的源码
/**
* Object类的
* public String toString() {
* return getClass().getName() + "@" + Integer.toHexString(hashCode());
* }
*/
Class cc1 = s1.getClass() ; //获取到了当前类的字节码文件对象 class 包名.类名
String name = cc1.getName(); //获取类的权限的名称--->包名.类名
//Integer类 静态方法public static String toHexString:将整数---转换十六进制数据 返回的字符串形式
//hashCode():代表对象的哈希码值:一个int类型的数据
String i = Integer.toHexString(s1.hashCode()) ;
System.out.println(name+"@"+i);
System.out.println();
Student s2 = new Student() ;
System.out.println(s2);
System.out.println(s1==s2) ;//==:基本类型(int,比较的是两个数据值是否相同),引用类型(比较的是地址值是否相同)
System.out.println("---------------------------------------") ;
// public final Class getClass()获取正在运行的java类或者接口(字节码文件对象)
Class c1 = s1.getClass() ;
System.out.println(c1) ;//class 包名.类名
Class c2 = s2.getClass() ;
System.out.println(c2) ;
System.out.println(c1==c2); //类就加载一次
//Class类中(Java反射中的讲):成员方法: String getName() ; 获取类的权限的名称(包名.类名的字符串形式 "全限定名称")
String name1 = c1.getName();
String name2 = c2.getName();
System.out.println(name1+"---"+name2);
System.out.println("---------------------------------------------------");
// public int hashCode() 返回对象的哈希码值
System.out.println(s1.hashCode()) ;
System.out.println(s2.hashCode());
System.out.println("高圆圆".hashCode());
System.out.println("高圆圆2".hashCode());
}
}
/学生类
public class Student extends Object{ //默认继承Object 隐藏了extends Object:不用写
private String name ;//姓名
private int age ;//年龄
private String gender ;//性别
//无参
public Student() {
}
//有参
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
//setXXX()/getXXX()
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
Object类的equals
public boolean equals(Object obj):比较两个对象是否相同
==和equals区别
==:
基本类型:比较的是数据值是否相同
引用类型:比较的是地址值是否相同
equals():Object类的方法
public boolean equals(Object obj) {
return (this == obj); //this--->就是p obj---->向上转型 p2 ==:比较是两个对象地址值
}
本身默认比较的是两个对象的地址值是否相同;当多个对象的成员信息是相同,认为是同一个人,所以
Object类需要建议所有的子类要重写equals(),比较的是对象的成员信息是否相同!
代码体现:
public class ObjectDemo3 {
public static void main(String[] args) {
Person p = new Person("张三丰",50) ;
System.out.println(p) ;
Person p2 = new Person("张三丰",50) ; //具体类对象创建
System.out.println(p2);
System.out.println(p==p2) ;
//public boolean equals(Object obj):比较两个对象是否相同
boolean flag = p.equals(p2);
System.out.println(flag); // p.equals(obj)--->参数:Object obj = new Person(); //
//false
/**
* 通过观察源码:
* public boolean equals(Object obj) {
* return (this == obj); //this--->就是p obj---->向上转型 p2 ==:比较是两个对象地址值
* }
*/
//String类重写了equals,比较字符串内容是否相同
String s1 = "hello" ;
String s2 = "hello" ;
System.out.println(s1.equals(s2)); //true
//大部分常用类都已经重写equals:比较内容是否相同
Integer i1 = 100 ;
Integer i2 = 100 ;
System.out.println(i1.equals(i2)); //true
}
}
import java.util.Objects;
public class Person {
private String name ;//姓名
private int age ; //年龄
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//idea自动重写
//alt+fn+ins--->eauals()and hashCode()
@Override
public int hashCode() {
return Objects.hash(name, age);
// 计算 成员信息中所有的属性的hashCode码值是否一样,如果一样,比较具体的name或者age是否一样
}
@Override
public boolean equals(Object o) { //p.equals(p2) //Person p2 = new Person("张三丰",50)
if (this == o) return true; //p == p2
if (o == null || getClass() != o.getClass()) return false; // this.getClass() !=p2.getClass(); 判断字节码文件对象是否不同
Person person = (Person) o; //向下转型
return age == person.age && name.equals(person.name);
//this.age == person.age && name是String类型----equals():已经重写Object的equals(),比较两个字符串内容是否相同
//50 == 50 && "张三丰".equals("张三丰")
}
}
String类
注意:
数组中有没有length()?字符串String类中有没有length()/集合中有没有length()方法?
数组没有length(),只有length属性
String的length():获取字符串长度
集合没有, size():获取集合长度
代码体现:
public class StringDemo {
public static void main(String[] args) {
//测试:空参构造
String s = new String();
System.out.println("s:"+s);
System.out.println(s.length());
System.out.println("----------------------------------------------") ;
//public String(char[] value):将字符数组构造出字符串
//已知字符串数组
char[] chs = {'我','爱','高','圆','圆'} ; //new char[]{'我','爱','高','圆','圆'}
String s2 = new String(chs) ;
System.out.println("s2:"+s2);
System.out.println(s2.length());
System.out.println("----------------------------------------------") ;
// public String(char[] value,int index,int length):将一部分字符数组转换成字符串
String ss = new String(chs,1,4);
System.out.println("ss:"+ss);
System.out.println(ss.length());
System.out.println("----------------------------------------------");
//public String(byte[] bytes) :将字节数组构造字符串
byte[] bytes = {97,98,99,100,101} ;
String s3 = new String(bytes) ; //在ASCII码表中寻找字符值
System.out.println("s3:"+s3) ;
System.out.println(s3.length());
System.out.println("-----------------------------------------------");
// public String(String original):将一个字符串值存储进去,构造成一个字符串对象
String s4 = new String("helloworld") ; //创建一个"helloworld"字符串对象
System.out.println("s4:"+s4) ;
System.out.println(s4.length());
}
}
面试题
String s1 = "hello" ;
String s2 = new String("hello");
他们分别创建了几个对象,有什么区别呢?
s1: 现在常量池中,是否存在这个常量,如果存在,直接返回地址值;否则,开辟新的空间地址值,赋值s1
s2:在堆内存中申请空间,然后常量"hello",
还需要在常量池中找是否存在这个常量,有,就返回地址,重新开辟常量池空间
共同点:都表示创建"hello"字符串实例
public class StringDemo2 {
public static void main(String[] args) {
String s1 = "hello" ;
String s2 = new String("hello");
System.out.println(s1==s2) ; //比较地址值 false
System.out.println(s1.equals(s2)) ; //true
//String类重写Object的equals方法,比较的字符串的内容是否相同;
/**
* 重写Object的源码
*
* class String{
* private final char value[]; 声明一个char类型的数组 value属性
*
*
*
* //Object anObject = new 任何子类对象() ;
* public boolean equals(Object anObject) {//s1.equals(s2 )
* if (this == anObject) {// if(s1==s2){}
* return true; //false
* }
* if (anObject instanceof String) { // s2这个变量 是否为 String类型的实例
* String anotherString = (String)anObject; //向下转型
* int n = value.length; //int n = s1.value.length ; //s1="hello" ; s1.value.lenth=5
* if (n == anotherString.value.length) { //n == s2.value.length // s2="hello" = 5
* char v1[] = value; //char v1[] = s1.value={'h','e','l','l','o'} ;
* char v2[] = anotherString.value; //cahr v2[] = s2.value ={'h','e','l','l','o'} ;
* int i = 0; //统计变量
* while (n-- != 0) { //n=5 ,4
* if (v1[i] != v2[i]) //if(v1[i] !=v2[i]) i=0 : v1[0]='h', v2[0]='h'
* i=1 v1[1] ='e', v2[1] ='e'
* return false;
* i++; //i ++--->1,2
* }
* return true; //true
* }
* }
* return false;
* }
*
* }
*/
}
}
字符串变量相加:常量池是否存在,不存在,开空间
字符串常量相加:先拼接,在常量池中找,有--->返回地址;否则,开辟空间
public class StringDemo3 {
public static void main(String[] args) {
String s1 = "hello" ;
String s2 = "world" ;
String s3 = "helloworld" ;
System.out.println(s3 == (s1+s2)); //false
System.out.println(s3.equals(s1+s2));//true
System.out.println("--------------------------------------");
System.out.println(s3 == "hello"+"world") ; //true
System.out.println(s3.equals("hello"+"world")) ;//true
}
}
String类型作为方法 形式参数的特点:
String类作为引用类型,当成为方法的形式参数,和基本类型的效果一致:
形式参数的改变,不影响实际参数
String是最为特殊的一种引用类型, 其他的引用类型,都是形式参数改变直接影响实际参数!比如StringBuffer
StringBuffer sb = "helloworld" ;
public class StringDemo {
public static void main(String[] args) {
String s = "helloworld" ; //常量赋值:开发中就是这么用的
System.out.println(s) ;
changeStr(s) ;
System.out.println(s);
}
public static void changeStr(String s) {//方法的形式参数String
s = s+"高圆圆" ;
System.out.println(s);
}
}
String类常用获取功能以及判断功能
public char charAt(int index):获取指定索引出的字符
public String concat(String str):字符串拼接功能
boolean contains(String s):判断字符串中是否包含指定的某个字符或者某个子字符串(按照第一个字符判断)
public boolean endsWith(String suffix):判断此字符串是否一指定的字符串结尾
public boolean startsWdith(String prefix):判断此字符串是否一指定的字符串开头
public boolean equals(Object anObject):比较是两个字符串的内容是否相同(必须一样)
public boolean equalsIgnoreCase(String anotherString):比较两个字符串内容是否相同,忽略大小写进行比较
public boolean isEmpty():判断字符串是否空(是否为空内容)
int length():获取字符串长度
public int indexOf(int ch):查询字符串中的某个字符第一次出现的索引值
public class StringDemo2 {
public static void main(String[] args) {
//字符串
String s = "helloworld" ;
String str = "helloWORLD" ;
String str1 = null ;//没有对象的,空对象
String str2 = "" ; //空字符串,有
// System.out.println(str1.concat("ak47"));
//java.lang.NullPointerException:如果某个对象都是null,没有对象,然后使用这个对象调用成员方法,就会错误
//解决方案:在操作之前,最好去对这个对象进行非空判断,防止空指针异常
if(str1!=null){
System.out.println(str1.concat("ak47"));
}else{
System.out.println("str1对象为null了");
}
// public char charAt(int index):获取指定索引出的字符
System.out.println(s.charAt(0));
System.out.println(s+"5+5"); //+:拼接符号,不是功能
// public String concat(String str):字符串拼接功能
String s2 = s.concat("高圆圆");//获取新的字符串
System.out.println(s2);
//boolean contains(String s)
System.out.println(s.contains("wor"));
//int length():获取字符串长度
System.out.println(s.length());
//public boolean endsWith(String suffix):判断此字符串是否一指定的字符串结尾
// public boolean startsWdith(String prefix):判断此字符串是否一指定的字符串开头
System.out.println(s.startsWith("h"));
System.out.println(s.endsWith("圆圆"));
System.out.println("---------------------------------------------");
//public boolean equals(Object anObject):比较是两个字符串的内容是否相同(必须一样)
//public boolean equalsIgnoreCase(String anotherString):比较两个字符串内容是否相同,忽略大小写进行比较
System.out.println(s.equals(str));
System.out.println(s.equalsIgnoreCase(str));
System.out.println("----------------------------------------------") ;
// public int indexOf(int ch):查询字符串中的某个字符第一次出现的索引值
System.out.println(s.indexOf('l'));
// public boolean isEmpty():判断字符串是否空(是否为空内容)
s = "" ;
System.out.println(s.isEmpty());
}
}
String类的常用的转换功能
public char[] toCharArray():将字符串转换成字符数组
byte[] getBytes() :使用平台默认的字符集(idea:utf-8:一个中文三个字节)
将字符串数据----变成字节数组 (编码)
public String[] split(String regex):使用分割符号---拆分成字符串数组 (分割功能)
public String toLowerCase():将字符串转换成小写
public String toUpperCase():将字符串转换成大写
public static String valueOf(int i) :这个方法参数可以是任意的Java类型:基本类型或者Object
public class StringDemo3 {
public static void main(String[] args) throws UnsupportedEncodingException { //可能出现异常
String s = "helloJavaEE" ;
/*System.out.println(s) ;
System.out.println(s.toString()) ;*/
// public char[] toCharArray():将字符串转换成字符数组
char[] chars = s.toCharArray();
//遍历
//进行反转
for(int x = chars.length-1; x >= 0 ; x --){
System.out.print(chars[x]+" ");
}
System.out.println();
System.out.println("----------------------------------------------------") ;
// byte[] getBytes() :使用平台默认的字符集(idea:utf-8:一个中文三个字节)
// 将字符串数据----变成字节数组 (编码)
byte[] bytes = s.getBytes();
for(int x = 0 ; x <bytes.length ;x++){
System.out.print(bytes[x]+" "); //104 101 108 108 111 74 97 118 97 69 69 寻找ASCII码表
}
System.out.println();
//如果是中文:一个中文:默认编码集utf-8:一个中文三个字节 第一个字节:永远负数
//gbk:一个中文两个字节 (国标)
//gbk3212是gbk的升级版:一个中文对应两个字节,包含特殊字符 (国标)
//iso-8859-1:拉丁文码表 :不考虑中文
//big-5:大五码 :港澳地区 :繁写字体
//JS编码:日本系统使用这个编码格式
//unicode:国际编码表(java)
String s2= "中国" ;
byte[] bytes2 = s2.getBytes();
//System.out.println(bytes2) ;//打印出地址值
//Arrays:数组工具类---提供 public static String toString(任何类型数据[] a): 将数组转换成字符串
System.out.println(Arrays.toString(bytes2));
//解码:bytes[]-----String String(byte[] bytes) /tring(byte[] bytes,字符集)
String result = new String(bytes2,"utf-8") ; //默认就是utf-8
System.out.println(result);
System.out.println("----------------------------------------");
// public String[] split(String regex):使用分割符号---拆分成字符串数组 (分割功能)
String str = "JavaEE-Python-C-C#-Hadoop-Php-GoLang" ;
String[] strArray = str.split("-");
for(int x = 0 ; x <strArray.length ; x++){
System.out.println(strArray[x]);
}
System.out.println("---------------------------------------");
// public String toLowerCase():将字符串转换成小写
// * public String toUpperCase():将字符串转换成大写
System.out.println(s.toLowerCase());
System.out.println(s.toUpperCase());
System.out.println("-------------------------------------");
//万能方法:public static String valueOf(int i) :这个方法参数可以是任意的Java类型:基本类型或者Object:
//将任何类型转换成String
int i = 100 ;//int
System.out.println(i); // 100--int类型
// System.out.println(i+"") ; //字符串 + 任何数据 + 字符串="字符串数据" ;
String s1 = String.valueOf(i);
System.out.println(s1);//"100":数字字符串
}
}
String类的截取功能
public String substring(int beginIndex):从指定位置处开始截取,默认截取到末尾
public String substring(int beginIndex,int endIndex):从指定位置开始截取,到指定位置结束,但是不包括endIndex位置,endIndex-1的位置(包前不包后)
Java语言中,只要某个成员方法涉及角标问题,而且有开始索引,有最终索引,不包含最终索引值,最终索引-1的位置
javaScript语言:跟Java语言这个是一样的
public class StringDemo4 {
public static void main(String[] args) {
//有一个字符串
String s = "helloworldJavaEE" ;
// public String substring(int beginIndex):从指定位置处开始截取,默认截取到末尾
System.out.println(s.substring(5));
//public String substring(int beginIndex,int endIndex):从指定位置开始截取,到指定位置结束,但是不包括endIndex位置,
//endIndex-1的位置(包前不包后)
System.out.println(s.substring(5,10));
}
}
String类的其他功能
public String replace(char oldChar,char newChar):替换功能 替换字符
public String replace(String oldStr,String newStr):替换功能 替换字符串
public String trim():去除字符串的前后端的空格
(一种场景数据以后在网络中传输,可能携带一些空字符,需要真实数据,需要将网络中的数据去除两端空格)" 真实数据 "
public int compareTo(String anotherString) :按照 字典顺序比较 ---翻阅源码
前端(js里正则表达式)和后端Java的正则表达式语法:
X:代表任意字符
X+: 表示X字符出现一次或多次 "abbbbbbbbbbbbbbbbbbbbbbbb" ---->"ab+"
x*: 表示x字符出现0次或者多次 "zooooooooo" /"z" ----- "z*"
public class StringDemo5 {
public static void main(String[] args) {
String str = "helloworld" ;
//public String replace(char oldChar,char newChar):替换功能 替换字符
System.out.println(str.replace('l','k'));
//public String replace(String oldStr,String newStr):替换功能 替换字符串
System.out.println(str.replace("world","高圆圆"));
System.out.println("---------------------------------------------------------");
//public String trim():去除字符串的前后端的空格
String str2 = " hello ";
System.out.println("str2:"+str2+"----");
//public String trim():去除字符串的前后端的空格
String str3 = str2.trim();
System.out.println("str3:"+str3+"----");
System.out.println("---------------------------------------------------------");
//面试题
//public int compareTo(String anotherString) :按照 字典顺序比较 ---翻阅源码
String s1 = "hello" ;
String s2 = "hel" ;
String s3 = "abc" ;
String s4 = "xyz" ;
System.out.println(s1.compareTo(s2)) ;
System.out.println(s1.compareTo(s3)) ;
System.out.println(s1.compareTo(s4)) ;
}
}
/**
* //jdk的String类的 按照字典顺序比较源码分析
* class String{
* private final char value[]; //字符数组 s1 "hello" s2 "hel" s3 "abc"
*
* public int compareTo(String anotherString) { //s1.compareTo(s2)
* int len1 = value.length; // int len1 = s1.value.length---->获取子一个字符串--字符数组长度 5
* int len2 = anotherString.value.length; //int len2 = s2.value.length---->字符数组长度3 3
* int lim = Math.min(len1, len2); //int lim = Math.min(5,3) :获取最小值 3 3
* char v1[] = value; //s1--->转换字符数组 v1[] 长度 5
* char v2[] = anotherString.value; //s2--->转换字符数组 v2[] 长度 3
*
* int k = 0; //统计变量 k=0开始
* while (k < lim) { //while(k<3) k=0 0<3 1<3 2<3 3<3while循环结束
* char c1 = v1[k]; //char c1 = v1[0] = 'h' c1=v1[1]-> 'e' c1 = v1[2] --'l'
* char c2 = v2[k]; //char 2 = v2[0] = 'h' v2[0] ='a' c2=v2[1] -'e' c2 = v2[2] -- 'l'
* if (c1 != c2) { //if(c1!=c2){ //不成立 //成立
*
*
* return c1 - c2; //return 'h'-'a' ---->ASCII码表 104-97 = 7
* }
* k++; //k=1 ,2 ,3
* }
* return len1 - len2; //s1的长度-s2长度 5-3 = 2
* }
*
* }
*
*/
键盘录入一个字符串数据,将字符串数据进行遍历:
public class StringTest {
public static void main(String[] args) {
//使用字符串的获取功能chartAt(int index):获取指定索引出的字符
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请您输入一个字符串:") ;
String line = sc.nextLine() ;
/* //第一次取
char c1 = line.charAt(0);
//第二次取
char c2 = line.charAt(1);
char c3 = line.charAt(2);
char c4 = line.charAt(3);
char c5 = line.charAt(4);
System.out.print(c1+" "+c2+" "+c3+" "+c4+" "+c5);*/
//循环改进
//方式1:length()和charAt(int index)结合
/* for(int x = 0 ; x < line.length(); x++){
char ch = line.charAt(x) ;
System.out.print(ch+" ");
}
System.out.println();*/
//方式2: char[] toCharArray()
char[] chars = line.toCharArray();
//遍历字符数组
for(int x = 0 ; x < chars.length; x++){
char ch = chars[x] ; //每一个字符
System.out.print(ch+" ");
}
}
}
键盘录入一个字符串,将第一个字符转换成小写
后面的字符转换成大写(String类转换功能toUperCase()/toLowerCase()以及截取功能substring(),拼接功能concat)
举例: 录入 "Helloworldjavaee"
输出结果:"hELLOWORLDJAVAEE"
public class StringTest2 {
public static void main(String[] args) {
//创建键盘录入对象
Scanner sc = new Scanner(System.in ) ;
//提示并录入数据
System.out.println("请输入一个字符串:") ;
String line = sc.nextLine();
/*//1)将第一个字符转换成小写: Helloworldjavaee hELLOWORLDJAVAEE
String s1 = line.substring(0,1) ;
//2)将上面的1)的字符转换小写
String s2 = s1.toLowerCase() ;
//3)将剩下的字符:转换成大写
String s3 = line.substring(1) ;
//4)将3)转换大写
String s4 = s3.toUpperCase() ;
//5) 将2) 和4)的内容拼接起来
String result = s2.concat(s4) ;
System.out.println("result:"+result);*/
//将的核心代码选中---->ctrl+alt+m--->抽取一个方法
//一步走:链式编程
String result = getString(line);
System.out.println(result);
}
//定义一个功能:截取之后转换
private static String getString(String line) {
String result = line.substring(0, 1).toLowerCase().concat(line.substring(1).toUpperCase());
return result;
}
}
需求:键盘录入一个字符串,统计这个字符串中大写字母字符,小写字母以及数字字符的个数(不考虑特殊字符)
分析:
0)定义三个统计变量
bigCount
smallCount
numberCount
1)创建键盘录入对象
2)录入字符串数据
3)可以将字符串---->转换成字符数组 char[] toCharArray()
4)遍历字符数组:
获取到一个字符 char ch = char数组对象[角标] ;
5)
来if...else if...else
ch的范围 'A' 'Z' 大写字母字符
bigCount++ ; 统计大写字母字符的
'a' 'z' 小写字母字符
smallCount++
‘0’ ‘9’ 数字字符
numberCount++
public class StringTest3 {
public static void main(String[] args) {
//定义三个 统计变量
int bigCount = 0 ; //统计大写字母字符
int smallCount = 0 ; //统计小写字母字符
int numberCount = 0 ; //统计数字字符
//创建键盘录入对象
Scanner sc = new Scanner(System.in) ;
//提示并录入数据
System.out.println("请输入一个字符串:");
String line = sc.nextLine();
//ctrl+alt+m
//转换成字符数组
char[] chs = line.toCharArray();
for(int x = 0 ; x < chs.length ; x ++){
//获取每一个字符
char ch = chs[x] ;
//判断
if(ch>='A' && ch <='Z'){
bigCount++ ;
}else if(ch>='a' && ch<='z'){
smallCount++ ;
}else{
numberCount++;
}
}
System.out.println("大写字母字符共有:"+bigCount+"个");
System.out.println("小写字母字符共有:"+smallCount+"个");
System.out.println("数字字符共有:"+numberCount+"个");
}
}
StringBuffer:线程安全的可变的字符串缓冲区,支持可变的字符序列
常用的构造方法:
StringBuffer():空参构造:创建一个支持缓冲区对象
StringBuffer(String str):将指定的字符串存储在字符串缓冲区中 (将String---StringBuffer)
这个类的部分功能和String :
int length(): 获取字符串缓冲区的长度
public int capacity():获取字符串缓冲区的容量 默认容量 16个字符,超过这个容量,会自己分配,使用的新的字符串的长度+16
public class StringBufferDemo {
public static void main(String[] args) {
//StringBuffer():空参构造:创建一个支持缓冲区对象
StringBuffer sb = new StringBuffer() ;
System.out.println(sb);
System.out.println(sb.length());
System.out.println(sb.capacity());
System.out.println("------------------------------------");
//StringBuffer sb2 = "helloworld" ; //后面String类型,前面StringBuffer
String s = "helloworld" ;
//StringBuffer(String str):将指定的字符串存储在字符串缓冲区中
StringBuffer sb2 = new StringBuffer(s) ;
System.out.println(sb2) ;//"helloworld"
System.out.println(sb2.length());
System.out.println(sb2.capacity());
}
}
StringBuffer常用的功能
public StringBuffer append(任意类型数据):添加任何类型数据到字符串缓冲区中
返回值字符串缓冲区本身
public StringBuffer insert(int offset,String xx):插入:在指定位置的前面插入一个新的字符序列
public StringBuffer reverse():将字符串缓冲区字符序列反转
public class StringBufferDemo2 {
public static void main(String[] args) {
//创建一个字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
System.out.println(sb);
//追加字符序列到缓冲区中
// sb.append(100).append(true).append('a').append(new Object()).append("helloworld") ;
sb.append("hello") ;
sb.append("world") ;
System.out.println(sb);
System.out.println("--------------------------------------");
// public StringBuffer insert(int offset,String xx):插入:在指定位置的前面插入一个新的字符序列
sb.insert(5,"高圆圆") ;
System.out.println(sb);
System.out.println("---------------------------------------") ;
//public StringBuffer reverse():将字符串缓冲区字符序列反转
sb.reverse() ;
System.out.println(sb);
}
}
StringBuffer和String的类型转换
String---->StringBuffer,目的为了StringBuffer的特有功能
StringBuffer--->String,结果需要是String类型
public class StringBufferDemo3 {
public static void main(String[] args) {
//String----StringBuffer
//有一个字符串
String s = "hello" ;
//StringBuffer sb = s;
//方式1:利用StringBuffer()无参构造方法+append(String str)
//创建一个字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
sb.append(s) ;
System.out.println(sb); //字符串缓冲区存储的数据内容 "hello",类型是StringBuffer
System.out.println("----------------------------------");
//方式2:利用StringBuffered的有参构造方法StringBuffer(String str)
StringBuffer sb2 = new StringBuffer(s) ;
System.out.println(sb2);
System.out.println("-----------------------StringBuffer转换成String-----------------------");
//StringBuffer --->String
StringBuffer buffer = new StringBuffer("helloworld") ;//字符序列是helloworld,外面的类型StringBuffer
//方式1:public String(StringBuffer buffer) ;String类的构造方法
String str = new String(buffer) ;
System.out.println(str) ; //内容"helloworld",类型String
System.out.println("-------------------------------------");
//方式2:public String toString() 显示的应该是字符串缓冲区中的实际的字符序列内容
String str2 = buffer.toString();
System.out.println(str2);
/*int i = 100 ;
String s4 = "100" ;*/
}
}
编写一个程序,将下面的一段文本中的各个单词的字母顺序翻转
"To be or not to be",将变成"oT eb ro ton ot eb"。
public class StringBufferTest {
public static void main(String[] args) {
// 1)String s = "To be or not to be"
String s ="To be or not to be" ;
System.out.println("反转之前:"+s);
//2)利用字符串的功能spilt(" "); 拆分---String[]
String[] strArray = s.split(" ");
//3)遍历字符串数组
System.out.print("反转之后:");
for(int x = 0 ; x < strArray.length; x++){
//获取到一个字符串
String strResult = strArray[x] ;
//创建一个字符串缓冲区对象
StringBuffer sb = new StringBuffer() ;
//追加并反转
sb.append(strResult).reverse();
System.out.print(sb.toString().concat(" "));
}
}
}
StringBuffer:作为方法的形式参数,形式参数的改变,直接影响实际参数;
public class StringBufferTest2 {
public static void main(String[] args) {
String s = "helloworld" ; //常量赋值:开发中就是这么用的
System.out.println(s) ;
changeStr(s) ;
System.out.println(s);
System.out.println("------------------------------------------");
StringBuffer sb = new StringBuffer("hello") ;
System.out.println(sb) ;//"hello"
changeStr(sb) ;
System.out.println(sb) ; //hello高圆圆
}
public static void changeStr(StringBuffer sb) {//方法的形式参数StringBuffer
sb.append("高圆圆") ; //追加功能: 追加新的内容到字符串缓冲区,使用堆内存空间地址值
System.out.println(sb);//hello高圆圆
}
public static void changeStr(String s) {//方法的形式参数String
s = s+"高圆圆" ;
System.out.println(s);
}
}
Integer:int类型,包装类型
基本类型:四类八种 自动装箱 引用类型(基本类型的包装类类型)
byte <--> Byte
short <--> Short
int <--> Integer(重点类)
long <--> Long
float <--> Float
double <--> Double
char <--> Character(重点类)
boolean <--> Boolean
代码的方式获取内容:
想知道int类型的取值范围? public static final int MAX_VALUE /public static final int MIN_VALUE
想知道整数值100对应的二进制,八进制,十六机制 ?
public static String toBinaryString(int i) :将整数值传进去,获取它二进制的字符串形式
public static String toOctalString(int i):将整数值传进去,获取它八进制的字符串形式
public static String toHexString(int i) :将整数值传进去,获取它十六进制字符串形式
public class IntegerDemo {
public static void main(String[] args) {
//想知道int类型的取值范围?
System.out.println(Integer.MIN_VALUE);//-2147483648
System.out.println(Integer.MAX_VALUE);//2147483647
System.out.println(Integer.toBinaryString(100));
System.out.println(Integer.toOctalString(100));
System.out.println(Integer.toHexString(100));
}
}
Integer类的构造方法
public Integer(int value):将int类型----Integer类型
public Integer(String s) throws NumberFormatException :将数字字符串 转换成Integer * throws:抛出异常的意思
抛出异常的可能性,当你传入的字符串如果不是数字字符串,jvm解析的时候,将这个异常就信息打印在控制台上
public class IntegerDemo2 {
public static void main(String[] args) {
int i = 100 ;//基本类型
// public Integer(int value):将int类型----Integer类型
Integer ii = new Integer(i) ;
System.out.println(ii) ;//100
ii += 200 ;
System.out.println(ii);
//public Integer(String s) throws NumberFormatException :将数字字符串 转换成Integer
//字符串: 必须是数字字符串 Integer是int类型包装类型
String s = "20" ;
Integer iii = new Integer(s) ;
System.out.println(iii);
}
/**
* 上面代码的使用反编译工具查看
* jdk5新特性:自动拆装箱 :基本类型--- 变成对应的引用类型 "装箱"
* 这些引用类型----->基本类型 ""拆箱
*
* int i = 100;
* Integer ii = new Integer(i); //装箱 int---->Integer
* System.out.println(ii);
*
* //我们的写的代码 ii+=200 ;
* //反编译工具---将 ii+=200:优化下面格式
*
* ii = Integer.valueOf(ii.intValue() + 200); //参数里面: ii.intValue()+ 200 : ii--->拆箱 int类型 +200 求和
* //参数里面完成计算---->int结果
* public static Integer valueOf(int i) :将int类型的结果---->Integer "装箱"
*
*
* System.out.println(ii);
*
*/
}
基本数据类型:八种 如何转换String
String---->基本类型
使用 int举例
int---->String :Integer.valueOf(int类型的值)
String---->int :Integer.parseInt(数字字符串)
public class IntegerDemo3 {
public static void main(String[] args) {
//int---->String
int i = 10 ;
//方式1:字符串拼接 符号+
System.out.println(i+"");//"10"
//方式2:int---->Integer:装箱---->String
//Intege(int i)
Integer ii = new Integer(i) ;
//Integer---->String :public String toString()
String s = ii.toString();
System.out.println(s) ; //"10"
//方式3:Integer类的静态方法:public static String toString(int i) (推荐)
String s2 = Integer.toString(i);
System.out.println(s2);
System.out.println("-----------------------------------------------") ;
//String --->int
String str = "100" ;// 数字字符串
//方式1:推荐 Integer 静态方法 public static int parseInt(String str): "最常用的"
int number = Integer.parseInt(str);
System.out.println(number); //100
//方式2:String---->Integer--->int
//Integer(String s)
Integer integ = new Integer(str) ;
//public int intValue()
int number2 = integ.intValue();
System.out.println(number2) ;
}
}
Character类:char类型 包装类类型
构造方法:
Character(char value) :将一个char类型的字符值构造成Character类对象
*常用成员方法:
判断字符是否为大写字母字符
public static boolean isUpperCase(char ch)
判断字符是否为小写字母字符
public static boolean isLowerCase(char ch)
判断字符是否为数字字符
public static boolean isDigit(char ch)
public class CharacterDemo {
public static void main(String[] args) {
//创建Character类对象
// Character(char value) :将一个char类型的字符值构造成Character类对象
Character character = new Character('a') ;
Character character2 = new Character((char)97) ;
System.out.println(character);
System.out.println(character2);
System.out.println("---------------------------------------------") ;
//判断字符是否为大写字母字符
//public static boolean isUpperCase(char ch)
System.out.println(Character.isUpperCase('A'));
System.out.println(Character.isUpperCase('a'));
System.out.println(Character.isUpperCase('9'));
System.out.println("--------------------------------------------") ;
//public static boolean isLowerCase(char ch)
System.out.println(Character.isLowerCase('A'));
System.out.println(Character.isLowerCase('a'));
System.out.println(Character.isLowerCase('9'));
System.out.println("--------------------------------------------") ;QQ`
//public static boolean isDigit(char ch)
System.out.println(Character.isDigit('A'));
System.out.println(Character.isDigit('a'));
System.out.println(Character.isDigit('9'));
}
}
Date类常用功能:
构造方法:
public Date():无参构造方法 :创建日期对象,获取当前系统时间的日期格式
:包含星期 年份 月份 月中的日期... (获取当前日期:使用这个)
public Date(long date):创建日期对象,和1970年1月1日时间有关系 00:00:00
成员方法:
public long getTime():获取时间的毫秒值
public class DateDemo {
public static void main(String[] args) {
//创建日期对象
Date date = new Date() ;
//当前系统时间
long t = date.getTime();
System.out.println(t);//1660791390307
System.out.println(date) ;//Thu Aug 18 10:30:39 CST 2022 Date日期格式
System.out.println("--------------------------------");
//定义一个long类型 变量
long time = 3600;
//public Date(long date)
Date date2 = new Date(time) ;
System.out.println(date2);
}
}
Date重点:日期文本格式和Date如何转换?
使用中间桥梁:DateFormat类 是一个抽象类,不能实例化,jdk提供更具体的子类:SimpleDateFormat
构造方法
public SimpleDateFormat(String pattern)
yyyy:年 MM:月 dd:月中日期 HH:小时 mm:分钟 ss:秒
成员方法:
Date---->String public String foramt(Date date) :格式化
String--->Date: public Date parse(String dateStr) throws ParseException: 解析
这个本身可能出现异常,如果解析的字符串的格式和 pattern参数的模式匹配,就出错了,解析失败!
public SimpleDateFormat(String pattern)
String s = "2008-5-12" ;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日") ;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd ") ;
public class DateDemo2 {
public static void main(String[] args) throws ParseException {
//Date---->String :格式化操作
Date date = new Date() ; //创建当前系统时间日期对象
System.out.println(date);
//使用中间桥梁 public SimpleDateFormat(String pattern)
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd") ;
// public String foramt(Date date) :格式化
String s = sdf.format(date);
System.out.println(s);
System.out.println("-------------------------------------") ;
//String--->Date: public Date parse(String dateStr) throws ParseException: 解析
String dataStr = "2008-5-12" ;
//创建中间桥梁 public SimpleDateFormat(String pattern)
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd") ;
//解析
Date d = sdf2.parse(dataStr);
System.out.println(d);
}
}
Random类常用功能:
构造方法:
创建随机数生成器对象
Random() 创建对象之后,调用nextInt()/nextInt(int n):每次随机数数字不一样的
public Random(long seed) :调用nextInt()/nextInt(int n):每次随机数数字一样的
不推荐用这个
成员方法
int nextInt():int类型的范围获取
int nextInt(int n):[0,n) :范围
实际用途:
有一个集合,集合里面存储的随机数,而且保证集合的元素必须唯一,将元素一一遍历出来;
List<Integer>:集合可以重复
Set:集合不可以重复
public class RandomDemo {
public static void main(String[] args) {
//创建Random对象;无参构造
Random random = new Random() ;
// public Random(long seed) :调用nextInt()/nextInt(int n):每次随机数数字一样的
// Random random = new Random(1001) ;
for(int x = 0 ; x <100; x++){
//int i = random.nextInt();
//int nextInt(int n):[0,n) :范围
int i = random.nextInt(100) +1;
System.out.println(i);
}
}
}
System类的一些常用功能:
public static void exit(int status) :参数为0,退出Jvm(正常终止),如果参数不为0,属于异常终止;
public static long currentTimeMillis():获取当前系统时间毫秒值
System类的复制数组 (经常在jdk原码里面简单 ,集合一些数据结构是"数组")
public static void arraycopy(Object src, 数据源(举例:原数组)
int srcPos, 原数组中某个位置
Object dest, 目的数据(目标数组)
int destPos, 目标数组的某个位置
int length 复制的长度
) :复制数组的一部分内容
public class SystemDemo3 {
public static void main(String[] args) {
int[] arr1 = {1,2,3,4,5} ;
int[] arr2 = {6,7,8,9,10} ;
//实现:将arr1的数组的一部分元素复制到另一个arr2数组中
//java.util.Arrays---->public static String toString(任意类型数组):将任何类型数组转换成字符串
/*System.out.println(arr1);
System.out.println(arr2);*/
System.out.println("复制之前:");
System.out.println(Arrays.toString(arr1));
System.out.println(Arrays.toString(arr2));
System.out.println("---------------------------------");
/**
* public static void arraycopy(Object src, 数据源(举例:原数组)
* * int srcPos, 原数组中某个位置
* * Object dest, 目的数据(目标数组)
* * int destPos, 目标数组的某个位置
* * int length 复制的长度
* * )
*/
System.arraycopy(arr1,1,arr2,2,2);
System.out.println("-------------------------------------------") ;
System.out.println(Arrays.toString(arr1));
System.out.println(Arrays.toString(arr2));
}
}
Collection集合
概述:
集合层次结构中的根界面 。 集合表示一组被称为其元素的对象。 一些集合允许重复元素,而其他集合不允许。 有些被命 令和其他无序。 JDK 不提供此接口的任何直接实现:它提供了更具体的子接口的实现,如 Set 和 List
常用功能:
boolean add ( E e ) 添加元素boolean remove ( Object o ) 删除元素boolean contains ( Object o ) 判断是否包含指定的元素boolean isEmpty():判断集合是否为空Object [] toArray (): 将集合转换成对象数组Iterator < E > iterator (): Collection 集合的迭代器void clear() :清空集合
int size():获取集合的元素数
public class CollectionDemo {
public static void main(String[] args) {
//不加入泛型---<>:集合里面规定,当创建集合对象的时候,就明确了集合中存储的元素的类型
//创建集合对象:接口多态
Collection c = new ArrayList() ;
System.out.println(c) ;
// boolean add(E e):添加任何类型元素 E---->理解为Object类型元素
/*boolean flag = c.add("hello"); //add返回值,只要添加元素,返回true
System.out.println(flag);*/
c.add("hello") ;//String
c.add(100) ; //int--->Integer
c.add('a') ;//char--->Character
c.add("world") ;//char--->Character
System.out.println(c);
System.out.println("-------------------------------------");
//boolean contains(Object o):判断集合中是否包含指定的元素
System.out.println(c.contains("hello"));
System.out.println(c.contains("高圆圆"));
// c.clear(); //清空集合
// System.out.println(c);
System.out.println(c.isEmpty());
System.out.println("-------------------------------------");
//int size():获取元素数
System.out.println(c.size());
}
}
使用Collection存储5个学生,学生有姓名,年龄,性别,需要遍历这个Collection集合,
使用高级功能普通用法:将集合转换成对象数组,遍历这个5个学生的信息.
public class CollectionDemo {
public static void main(String[] args) {
//创建一个Collection集合
Collection c = new ArrayList() ;
//创建5个学生对象
Student s1 = new Student("王昭君",35,"女") ;
Student s2 = new Student("杨贵妃",36,"女") ;
Student s3 = new Student("西施",25,"女") ;
Student s4 = new Student("貂蝉",20,"女") ;
Student s5 = new Student("高圆圆",43,"女") ;
//给集合中添加5个学生
c.add(s1) ;
c.add(s2) ;
c.add(s3) ;
c.add(s4) ;
c.add(s5) ;
System.out.println(c);
//遍历Collection
//public Object[] toArray():将集合转换成Object[] 对象数组
Object[] objects = c.toArray() ; //Objet[]--->5个学生类型
//数据类型:Object 里面的内容相当于这种格式Object 对象名 = new Student() ; 向上转型
for(int x = 0 ; x < objects.length ; x++){
//String s = (String) objects[x]; //Objects[x]里面的数据类型:Object--->指向任意子类 Student
// System.out.println(s);
//心里清楚:objects 数组对象存的数据类型是什么
//向下转型 :Student类型
Student s = (Student) objects[x]; //通用使用Student类型变量 s接收
System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGender());
}
}
}
public class Student {
private String name ; //姓名
private int age ; //年龄
private String gender ;//性别
public Student() {
}
public Student(String name, int age, String gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
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 String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
", gender='" + gender + '\'' +
'}';
}
}
泛型
1 :泛型是一种特殊的类型,它把指定类型的工作推迟到客户端代码声明并实例化类或方法的时候进行。也被称为参数化类型,可以把类型当作参数一样传递过来,在传递过来之前我不明确,但是在使用的时候我就用明确了。2 :泛型的好处A: 提高了程序的安全性B: 将运行期遇到的问题转移到了编译期C: 省去了类型强转的麻烦3.泛型书写格式Collection<Student> c1 = new ArrayList<>() ;
public class CollectionDemo3 {
public static void main(String[] args) {
//加入泛型的操作
//创建集合
Collection<Student> c = new ArrayList<>() ;//现在这个集合中只能存储Student类型
//创建5个学生
Student s1 = new Student("秦昊",23,"男") ;
Student s2 = new Student("张波",25,"男") ;
Student s3 = new Student("高珊",22,"女") ;
Student s4 = new Student("郑超帆",20,"男") ;
Student s5 = new Student("高圆圆",30,"女") ;
//添加到集合中
//c.add("hello") ; 不能存储其他类型
c.add(s1) ;
c.add(s2) ;
c.add(s3) ;
c.add(s4) ;
c.add(s5) ;
//获取Collection集合的迭代器
//Iterator<E> iterator()
//迭代器的泛型和集合中存储的泛型一致
Iterator<Student> it = c.iterator();
//遍历
while(it.hasNext()){//是否有下一个元素
//获取
Student s = it.next();//避免强转了
System.out.println(s); //toString
System.out.println(s.getName()+"---"+s.getAge()+"---"+s.getGender());
}
}
}
List集合
有序的 collection (也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。与 set 不同,列表通常允许重复的元素。
List接口成员方法
void add ( int index , E element ) 在指定位置处添加元素E remove ( int index ) 删除指定位置的元素E get ( int index ) 获取指定位置的元素E set ( int index , E element ) 在指定位置设置指定的元素ListIterator listIterator () 列表迭代器
List集合的特点:
List集合的特点:
1)元素可以重复
2)存储和取出一致(有序性)
List集合 继承Collection接口,目前存储字符串,并遍历? 有几种方式
Objec[] toArray() 将集合转换成对象数组
Iterator<E> iterator() Collection的迭代器
自己的特有的遍历方式
后面这两个:List<E></>集合有功能
1)普通for循环: 使用集合 int size():获取元素数
E get(int index):通过角标获取元素
2)集合的列表迭代器ListIterator listiterator()
ListIterator:
boolean hasNext():是否有下一个元素
E next():获取下一个元素
最终的写法:开发中写的,增强for循环:jdk5的新特性
增强for循环的出现目的:是为了代替迭代器的使用(为了简化代码的书写),一般在集合中用
增强for循环遍历数组少,数组:建议普通循环
for(集合中存储的类型 变量名:集合对象或者数组对象){
使用这个变量名即可!
}
public class ListDemo {
public static void main(String[] args) {
//创建List集合对象存储字符串
List<String> list = new ArrayList<>() ;
list.add("hello") ;
list.add("world") ;
list.add("javaEE") ;
list.add("android") ;
//第一种方式
Object[] objects = list.toArray();
for(int x = 0 ;x <objects.length ;x++){
String s = (String) objects[x];
System.out.println(s);
}
System.out.println("---------------------------------------") ;
//迭代器:带上泛型
//方式2: Iterator<E> iterator() Collection的迭代器
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
//获取下一个元素
String s = iterator.next();
System.out.println(s);
}
System.out.println("-----------------------------------------") ;
//List集合 特有遍历方式
//1)普通for循环: 使用集合 int size():获取元素数
// E get(int index):通过角标获取元素
for(int x= 0 ;x < list.size();x++){
//通过角标获取元素
// E get(int index):通过角标获取元素 ,返回值类型和集合存储的类型一致
String s = list.get(x);
System.out.println(s);
}
System.out.println("-----------------------------------------------------") ;
/**
* 集合的列表迭代器ListIterator listiterator() :默认正向遍历
* ListIterator:
* boolean hasNext():是否有下一个元素
* E next():获取下一个元素
*
* 反向遍历
* boolean hasPrevious():判断是由上一个元素
* E previous():获取上个元素
* 必须先有正向遍历,才有反向遍历
*
*
*/
ListIterator<String> lit = list.listIterator();//获取List集合专有迭代器
while(lit.hasNext()){//判断是否有下一个元素,有才获取
String s = lit.next();//获取下一个元素
System.out.println(s) ;
}
System.out.println("---------反向遍历-------------");
/**
* 反向遍历
* boolean hasPrevious():判断是由上一个元素
* E previous():获取上个元素
* 必须先有正向遍历,才有反向遍历
*/
while(lit.hasPrevious()){
String s = lit.previous();
System.out.println(s);
}
System.out.println("-------------------------------------------") ;
// for(集合中存储的类型 变量名:集合对象或者数组对象){
// * 使用这个变量名即可!
// *
// *
// * }
for(String s:list){
//使用变量s
System.out.println(s);
}
}
}
List集合去重
1)假设就创建List集合对象,里面存储重复的字符串数据
2)创建一个新的List集合,空集合
3)遍历以前的集合,获取以前的所有元素,在新的集合中判断,是否包含这个元素,如果不包含,说明不重复
将元素添加到新集合中,如果包含,说明重复,重复元素不需要加入到新集合中(找考虑不包含的情况)
4)最终,遍历新的集合,就是一个不重复的元素!
刚才存储List<String> String类----jdk提供的
刚才存储重复的字符串并保证元素唯一,里面用到集合的contains(Object a)
里面依赖于一个indexof
public boolean contains(Object o) {
return indexOf(o) >= 0; //查询元素
}
indexOf方法又依赖于Object的equals方法,--->contains(Object o)间接依赖于Object的equals方法
而List<String>,里面是String类型,本身重写了Object的equals方法,所以比较的是字符串内容是否相同
但是我们List<Student>,自定义的类型,所有必须重写Object的equals(),
才能比较的是对象的成员信息是否相同,相同认为是同一个人
不重写比较的就是地址值是否相同
public class ListTest3 {
public static void main(String[] args) {
//创建一个集合
List<Student> list = new ArrayList<>() ;
//创建学生对象
Student s1 = new Student("张三",25) ;
Student s2 = new Student("张三",25) ;
Student s3 = new Student("高圆圆",43) ;
Student s4 = new Student("高圆圆",43) ;
Student s5 = new Student("高圆圆",22) ;
Student s6 = new Student("张嘉译",50) ;
Student s7 = new Student("张嘉译",50) ;
//将7个学生添加到list集合中
list.add(s1) ;
list.add(s2) ;
list.add(s3) ;
list.add(s4) ;
list.add(s5) ;
list.add(s6) ;
list.add(s7) ;
//创建一个的空的集合
List<Student> newList = new ArrayList<>() ;
//遍历以前的集合,
for(Student s:list){
//获取到每一个学生对象s
//在新集合中判断如果新集合中不包含这个s,说明不重复
if(!newList.contains(s)){
//将学生对象s添加到新集合中
newList.add(s) ;
}
}
//遍历新集合
for(Student s:newList){
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
public class Student {
private String name ; //姓名
private int age ; //年龄
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//alt+fn+ins--->eauals and hascode
@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.equals(student.name);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
return result;
}
}
选择排序:
import java.util.Arrays;
public class SelectSort {
public static void main(String[] args) {
int [] arr={62,45,78,35,12};
System.out.println("排序前:");
System.out.println(Arrays.toString(arr));
System.out.println("排序后:");
int[] arr2= extracted(arr);
System.out.println(Arrays.toString(arr2));
}
private static int [] extracted( int[] arr) {
for (int x = 0; x< arr.length-1; x++){
for (int y = x+1; y< arr.length; y++){
if (arr[x]>arr[y]){
int temp= arr[x];
arr[x]= arr[y];
arr[y]=temp;
}
}
}
return arr;
}
}
ArrayList子实现类
底层数据结构是数组,查询快,增删慢; 线程不安全,效率高
Vector集合子实现类
底层数据结构是数组,查询快,增删慢;线程安全,效率低
public void addElement ( E obj ) 添加元素 , 类似于 List 的 add 方法public E elementAt ( int index ) 获取指定位置的元素 , 类似于 List 集合的 get 方法public Enumeration elements () 遍历所有的元素 , 类似于 List 的迭代器
public class VectorDemo {
public static void main(String[] args) {
//创建Vector集合对象
Vector<String> v = new Vector<>() ;
//添加元素
//public void addElement(E obj):添加任意元素 如果E类型确定了,就只能添加这个数据类型
v.addElement("hello");
v.addElement("world");
v.addElement("JavaEE");
v.addElement("高圆圆");
//特有遍历方式1;
// public Enumeration<E> elements():获取组件(返回值是枚举接口---产生一系列元素)
// 类似于Collection集合的类似于Collection集合的Iterator iterator()迭代器
Enumeration<String> enumeration = v.elements();
/**
* Enumeration枚举接口
* boolean hasMoreElements() 判断是有更多的元素
* --->类似于Iterator迭代器里面的hasNext()
* E nextElement() :获取下个元素
* --->类似于Iterator迭代器里面的next():获取下一个元素
*/
while(enumeration.hasMoreElements()){ //判断是否有更多的元素
String s = enumeration.nextElement();
System.out.println(s);
}
System.out.println("-------------------------------------------------") ;
//特有方式2
//public E elementAt(int index)通过角标获取元素 ---类似于List集合的public E get(int index)
//结合 int size()获取集合长度(集合元素数量)
for(int x = 0 ; x < v.size(); x++){
//通过角标获取元素
String s = v.elementAt(x);
System.out.println(s);
}
System.out.println("--------------------------------------------------" ) ;
//最终归结于增强for
for(String s:v){
System.out.println(s);
}
}
}
LinkedList子实现类
底层数据结构是链表,查询慢,增删快;线程不安全,效率高
LinkedList集合特有功能
public void addFirst(E e):添加到链表的开头
public void addLast(E e):添加到链表的末尾
public E getFirst():获取链表的第一个元素
public E getLast():获取链表的末尾的元素
public E removeFirst():删除链表第一个元素
public E removeLast():删除链表的最后一个元素
public void push(E e):推送到链表开头(压栈)---等价于public void addFirst(E e):添加到链表的开头
public E pop():弹出最后一个元素(弹栈) 等于removeFirst() :将第一个元素删除并返回
public class LinkedListDemo {
public static void main(String[] args) {
//创建LinkedList集合对象
LinkedList<String> link = new LinkedList<>() ;
//添加字符串
//public void addFirst(E e):添加到链表的开头
// public void addLast(E e):添加到链表的末尾
link.addFirst("hello") ;
link.addFirst("world") ;
link.addFirst("java") ;
link.addLast("javaEE");
System.out.println(link) ;
/* public E getFirst():获取链表的第一个元素
public E getLast():获取链表的末尾的元素
public E removeFirst():删除链表第一个元素
public E removeLast():删除链表的最后一个元素*/
String first = link.getFirst();
System.out.println(first) ;
String last = link.getLast();
System.out.println(last);
System.out.println(link.removeFirst()); //删除第一个并返回第一个元素
System.out.println(link);
}
}
模拟进栈出栈(先进后出)
import java.util.LinkedList;
/**
* 使用LinkedList的特有功能模拟栈结构特点?
* 栈结构:先进后出
*
* 相当于自定义一个类,这个类完成一些功能,需要使用到LinkedList集合的特有功能
* 这个功能添加元素(压栈)--->使用LinkedList的addFirst():每一次将元素添加到链表开头
* 获取元素:(弹栈)----->使用LinkedList集合的removeFist():相当于pop:弹栈,删除第一个并获取第一个元素
*/
public class MyStack {
//成员变量的位置
private LinkedList linkedList ;
//定义一个构造方法
public MyStack(){
//创建一个LinkedList集合对象
linkedList = new LinkedList() ;
}
//定义一个功能:添加元素的方法 压栈
public void addElement(Object obj){ //添加任何Java类型 "hello","world"
//间接用到LinkedList的特有功能
linkedList.addFirst(obj); // "world","hello"使用linkedList就添加开头了
}
//定义一个功能,弹栈: 取出元素 ,将LinkedList集合第一个元素删除并返回
public Object getElement(){
return linkedList.removeFirst() ;//删除第一个并返回
}
//提供判断功能
public boolean isEmpty(){
return linkedList.isEmpty() ;
}
}
public class Test {
public static void main(String[] args) {
//创建MyStack对象
MyStack my = new MyStack() ;
my.addElement("hello") ;
my.addElement("world") ;
my.addElement("javaEE") ;
my.addElement("蔡徐坤");
while(!my.isEmpty()){//不为空,在获取
System.out.println(my.getElement());
}
}
}
set集合
一个不包含重复元素的 collection 。Set 案例存储字符串并遍历存储自定义对象并遍历
HashSet实现类
不保证set的迭代顺序;特别是它不保证该顺序恒久不变
Set集合的特点:保证元素唯一,而且不能保证迭代次序
唯一,无序性(元素不重复,不能保证顺序---哈希表(key-value键值对)完成的(桶状结构))
创建HashSet(Set接口的子实现类之一)集合对象来存储String类型,重复的数据,看效果
为什么保证元素能唯一的:
HashSet底层依赖于Map<K,V>接口的子实现类HashMap<K,V>实现的
HashSet的add()方法依赖于HashMap的put 方法,这个方法间接依赖于Object类的equals和hashCode()
而现在存储String类型,String底层已经重写了hashCode()和equals方法
HashCode:比较字符串的哈希码值(理解为地址值)是否一样,如果一样,比较内容是否一样
英文可以,但是中文,繁写字体或简写字体,hashCode一样,内容可能不一样;必须重写equals,比较内容是否相容!
HashSet<Student>如果存储的是自定义对象,必须自定义的类要重写Object类的equals和hashCode(),否则不是唯一的
public class HashSetDemo {
public static void main(String[] args) {
//创建HashSet集合对象
Set<String> set = new HashSet<>() ;//String---->jdk提供的类
//添加元素
set.add("hello") ;
set.add("hello") ;
set.add("javaEE") ;
set.add("world") ;
set.add("world") ;
set.add("android") ;
set.add("android") ;
set.add("python") ;
set.add("python") ;
//遍历增强for
for(String s:set){
System.out.println(s) ;
}
}
}
使用HashSet集合存储自定义对象,学生类型Student,姓名和年龄
保证Student对象唯一的,不能重复(成员信息一样,是同一个人)!
遍历学生信息
因为8个对象:地址值不一样,不重写Object的equals:比较的地址值是否相同,地址值都不相同,肯定都存进去了!
重写Object类的equals和hashCode(),
public class HashSetDemo2 {
public static void main(String[] args) {
//创建HashSet集合对象
HashSet<Student> hs = new HashSet<>() ; //具体类直接创建
//创建学生对象
Student s1 = new Student("李帅",25) ;
Student s2 = new Student("李帅",25) ;
Student s3 = new Student("蔡同斌",22) ;
Student s4 = new Student("蔡同斌",25) ;
Student s5 = new Student("杨本初",26) ;
Student s6 = new Student("杨本初",26) ;
Student s7 = new Student("马保国",66) ;
Student s8 = new Student("马保国",66) ;
//添加到set集合中
hs.add(s1) ;
hs.add(s2) ;
hs.add(s3) ;
hs.add(s4) ;
hs.add(s5) ;
hs.add(s6) ;
hs.add(s7) ;
hs.add(s8) ;
//增强for遍历
for(Student s:hs){
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
//学生类
public class Student {
private String name ; //姓名
private int age ; //年龄
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
// 重写Object类的equals和hashCode(),
@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.equals(student.name);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
return result;
}
}
TreeSet实现类
使用元素的自然顺序对元素进行排序或者根据创建 set 时提供的Comparator 进行排序,具体取决于使用的构造方法。TreeSet是如何保证元素的排序和唯一性的,底层数据结构是红黑树(红黑树是一种自平衡的二叉树)