欢迎访问悦橙教程(wld5.com),关注java教程。悦橙教程  java问答|  每日更新
页面导航 : > > > 文章正文

JavaSE,

来源: javaer 分享于  点击 24074 次 点评:270

JavaSE,


JavaSE

一、Java基础语法

1、基本常识

JRE = JVM+SE标准类库 JDK=JRE+开发工具集

java关键字:

2、常量与变量

​ 简单理解什么是变量:

​ java中变量的命名规则:

​ 满足标识符规则,单个单词 小写,多个单词 首单词小写 后续单词开头大写,命名尽量简单具有语言含义,命名长度无限制。

​ 标识符命名规则: 字母+数字+_+$,首字母不能是数字,不能是java的关键字和保留字,严格区分大小写

​ java中类的命名规则:

​ 每个单词 的 首字母大写

​ 整型的字面值可以是二进制、十进制、八进制和十六进制。

​ 浮点型字面值默认情况下表示double类型,也可以在值后加d或D,表示float类型,则需要在字面值后加f或F。

​ 基本数据类型变量按作用范围分为 类级、对象实例级、方法级、块级 Java中内存分为 栈、堆、常量池等 当前主方法中局部变量是存储在栈当中的。

​ 字符型字面值用 单引号(英文) 内的 单个字符 表示 整形可以赋值给字符型,此时整形值视为ASCII ASCII主要用于显示英文和西欧字母,使用7位或8位二进制组合来表示128或256种可能的字符(标准7位二进制 后128位扩展ASCII表示特殊字符)

​ unicode编码的目标是支持世界上所有的字符集 unicode表示法,在值前加前缀\u 范围 \u0000到 \uFFFF

​ Java中Boolean值只能是 true 和 false,字符串字面值是双引号引起来的 0个 或 多个 字符,其中空格也占一个字符

​ 转义字符:

​ java中的自动类型转换:

​ java中常量名一般使用大写(单词间以下划线分割)

3、运算符

​ 复合赋值运算符:

​ 当字符串与基本数据类型进行加法运算时,实际上是在底层进行 字符串拼接运算

​ 关系运算符 ‘A’>'B’比较的是两个字符的ASCII值 浮点型与整数进行比较,只要值相等就返回true。

​ 如何从键盘输入数据:

​ import java.util.Scanner;

​ Scanner s=new Scanner(System.in);

​ int n=s.nextInt();

​ && 和 || 又叫短路运算符 第一个表达式的值能决定结果时,右边的表达式就不再运算了

​ & “与”运算符的结果:

​ 运算符的优先级:

4、流程结构

​ switch 表达式的值的类型:

​ switch中,case和其后的常量之间必须有一个空格。

​ while循环中 1. n的值必须先进行初始化 2.循环变量n的值必须被改变

​ do{}while; 循环 1. 至少执行一次 2. 循环条件后的分号不能丢

​ 多重循环中,break语句只向外跳一层

​ continue只能用在循环里,可以结束当前循环的执行,但是依然进行下一次循环的执行

​ debug调试: 1.设置断点 2.打开debug模式 3.单步调试 F6是单步调试的快捷键

5、数组

​ 数组是 相同类型 的数据 按顺序 组成的一种 引用数据类型

​ 数组的声明: 数据类型[] 数组名; 数据类型 数组名[];

​ 语法格式一:先声明后创建 数据类型[] 数组名; 数组名=new 数据类型[数组长度]

​ 语法格式二:声明的同时创建数组 数据类型[] 数组名=new 数据类型[数组长度]; 注意:数组长度必须指定!

​ 局部变量没有默认值,数组有默认值。 声明的同时给数组赋值,叫数组的初始化,如int[] arr={1,2,3,4,5}; 数组元素的引用: 数组名[下标]; 下标从零开始

​ 增强型for循环: 又叫foreach循环

​ int[] arr={1,2,3,4,5};

​ for(int n:arr) {

​ System.out.println(n);

​ }

​ for(int n=0;n<a.length;n++)与for(int n:a)功能相同

​ 数组 array 的长度一旦定义就不能再改变了。

6、方法

1)方法重载

方法重载:方法名相同;参数列表不同(顺序,个数,类型);方法返回值、访问修饰符任意 ;与方法的参数名无关(仅仅参数名不一样会报错)

​ 为什么要方法重载? 有时候一个方法名,要用到很多次,而且每次跟每次的参数都不一样,而且这个方法名,特别适合某个业务(比如登录),这个时候你变成其他的方法名,对大家来讲都很别扭,这时候就用到重载的概念了。

​ 同类中方法使用:参数的传递问题: 主方法中调用方法必须创建对象,同类中其他方法调用无需创建对象,直接使用名字即可

​ 数组作为方法参数传值问题: 基本数据类型传值不会影响主方法中的值,引用数据类型的传值会影响主方法中的值。对象作为方法参数也会对对象内容进行影响,对象用类来声明的,本身也是一个引用的数据类型。

​ 可变参数:参数的数量不确定,可以随时变化 例:public void sum(int… n){} 参数列表中有两个或以上参数,可变参数一定是放在最后的。

​ 可以将数组的值传递给 可变参数列表,但数组作为参数时,不能将多个值传递给数组

二、Java面向对象

7、面向对象

​ 当你拿到一个问题时,你分析这个问题不再是第一步先做什么,第二步再做什么,这是面向过程的思维,**你应该分析这个问题里面有哪些类和对象,这是第一点,然后再分析这些类和对象应该具有哪些属性和方法。这是第二点。最后分析类和类之间具体有什么关系,这是第三点。**面向对象有一个非常重要的设计思维:合适的方法应该出现在合适的类里面。

​ 单一职责原则:建议一个类有且只有一个引起功能变化的原因。

​ 包的推荐命名规范: 小写字母+域名反写

1)栈、堆、常量池、方法区

1、堆空间用于存储使用new关键字所创建的对象和数组,由JVM的自动垃圾回收器来管理。被所有线程共享。此外,创建对象和数组时会向栈中添加对象的引用变量,取值等于数组或者对象在堆内存中的首地址;

2、栈空间用于存储程序运行时在方法中声明的所有的局部变量、对象的引用变量;当超过变量的作用域后,java会自动释放掉为该变量所分配的内存空间。存在栈中的数据同一个线程可以共享

​ 假设我们同时定义 int a = 3; int b = 3; 编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找有没有字面值为3的地址,没找到,就开辟一个存放3这个字面值的地址,然后将a指向3的地址。接着处理int b = 3;在创建完b的引用变量后,由于在栈中已经有3这个字面值,便将b直接指向3的地址。这样,就出现了a与b同时均指向3的情况。特 别注意的是,这种字面值的引用与类对象的引用不同。假定两个类对象的引用同时指向一个对象,如果一个对象引用变量修改了这个对象的内部状态,那么另一个对象引用变量也即刻反映出这个变化。相反,通过字面值的引用来修改其值,不会导致另一个指向此字面值的引用的值也跟着改变的情况。如上例,我们定义完a与 b的值后,再令a=4;那么,b不会等于4,还是等于3。在编译器内部,遇到a=4;时,它就会重新搜索栈中是否有4的字面值,如果没有,重新开辟地址存放4的值;如果已经有了,则直接将a指向这个地址。因此a值的改变不会影响到b的值。

3、方法区是一块所有线程共享的内存区域,用于存放类的信息,比如类的字段、方法、常量池等常量池存放基本类型的常量字面值、以“”定义的字符串等。方法区的大小决定系统可以保存多少个类。如果系统定义太多的类,导致方法区溢出。虚拟机同样会抛出内存溢出的错误。

2)构造方法

1、构造方法与类同名且没有返回值

2、只能在对象实例化的时候调用(new关键字的好搭档)

3、当没有指定构造方法时,系统会自动添加无参的构造方法;当有指定构造方法时,无论是有参、无参的构造方法,都不会自动添加无参的构造方法;一个类中可以有多个构造方法

3) THIS

​ 简单来说,this在类中就是代表当前对象,谁调用谁就是当前对象。引用成员变量。如果在某个变量前面加上一个this关键字,其指的就是这个对象的成员变量或者方法,而不是指成员方法的形式参数或者局部变量。

8、封装

封装:将类的某些信息隐藏在类内部,不允许外部程序直接访问,只能通过该类提供的方法来实现对隐藏信息的操作和访问。隐藏对象的信息,留出访问的接口

1)static

1、定义静态变量。当在类中定义了一个静态变量时,不管使用这个类定义多少对象,这些对象中的static方法对应的变量始终指向了同一内存空间,对任意一个对象修改其中的内容,都会影响其他静态变量的值。

​ 1 类对象共享 2 类加载时产生,生命周期长 3 既可以通过对象名访问,也可以通过类名访问

2、static修饰方法 称 静态方法,也叫类方法,推荐调用的方式为 类名.成员

3、static不能用来修饰 类,也不能修饰 成员方法内的局部变量

4、静态方法中不能直接访问同一个类中的非静态成员,只能直接调用静态成员。静态方法中也不能使用this, 只能通过对象实例化后,对象.成员/方法 的方式访问类中的非静态成员。

5、类方法中调用本类的类方法时可直接调用,也可以通过类名.方法名 直接调用其他类的类方法

2)代码块

1、普通代码块——如 public void getName() { }——顺序执行,先出现,先执行

2、直接使用 { } 定义一个构造代码块,它每次创建对象都会调用一次,优先于构造方法执行。

注:构造代码块不是优先于构造函数执行,而是依托于构造函数。也就是说,如果你不实例化对象,构造代码块是不会执行的。构造代码块每次实例化对象时都会执行一次。

3、static{} 静态代码块,类加载时调用,优先于构造代码块执行。 静态代码块无论实例化多少个对象,都只执行一次。

4、构造代码块中可以给普通成员赋值,静态代码块中只能直接访问类中静态变量,除非实例化对象通过对象访问。

9、继承

继承:体现一种类与类之间的关系 使用已存在的类的定义作为基础类建立新类 新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。

java中的继承只能是单继承 子类可以访问父类非私有成员。

1)方法重写

方法重写:

1、有继承关系的子类中

2、方法名,参数列表(类型、顺序、个数)必须相同

3、与参数名无关

4、访问修饰符,访问范围需要大于等于父类方法的访问范围

5、子类的返回值类型必须相同,或者是,可以允许父类的子类作为返回值类型

6、子类抛出的异常类型要小于或者等于父类抛出的异常类型。

2)访问修饰符

1、private :只允许在本类中进行访问

2、default(不加修饰符):允许在当前类、同包子类/同包非子类 访问,无法在跨包子类/跨包非子类中调用

3、protected:允许在当前类、同包子类/同包非子类、跨包子类调用,但不能在跨包非子类中调用

4、public :访问权限最大,运行在任意位置访问

3)继承初始化

super :父类对象的引用。在继承关系中,父类的构造方法是不允许被继承的,也不允许被重写。

继承类在进行初始化时,会优先加载父类的静态成员,然后加载子类的静态成员,接下来构造时会逐层完成父类对象加载,即先去找父类,最终到object类(所有类的父类),接下来逐层回到父类加载成员属性,执行构造代码块,执行构造方法。最后完成子类对象构造。

当进行静态成员加载时,访问修饰符不影响成员加载顺序,与成员的书写顺序有关。

**子类构造过程中必须调用,而且默认调用的是父类的无参构造方法。**当父类中没有无参构造方法的时候,子类在继承时就会出错。可以通过super() 调用父类允许被访问的其它构造方法和属性,super( ) 必须放在子类构造方法的有效代码的第一行。 虽然父类的构造不允许被继承、不允许被重写,但是会影响子类对象的实例化。

构造方法调用时,super和this不能同时出现,因为它们会抢占第一行的位置

4)Object

Object类是所有类的父类。继承Object中的equals方法时,比较的是两个引用是否指向同一个对象,作用相等于 == 符号。 String类中重写的 equals方法,比较的是两个字符串里的内容。

toString() 方法: 输出对象名时默认调用,继承自Object中的 toString() 方法,输出 包.类名(类型信息) +@ +内存位置(地址信息)。String类型中重写了 toString() ,toString(对象名)会直接输出 对象值。

5)final

1、final class : 表示该类没有子类 public final class \ final public class 两种写法都正确

2、如果 final 添加在方法前,那么该方法不能被子类所重写。但是在子类当中仍然可以正常的被继承使用。注: final不能修饰构造方法。

3、final 可以用来修饰变量:

​ 修饰方法内局部变量:只要在具体使用之前进行赋值即可,一旦被赋值就不允许被修改

​ 修饰类成员属性:修饰后可以对该属性赋值的地方:1、定义直接初始化 2、构造方法 3、构造代码块(也只能在这三个地方被赋值,其它地方不允许进行赋值操作,再次强调!)不初始化,编译前会直接报错

另外,final 修饰 引用数据类型时,实例化后不允许对引用地址重新修订,但对象里的属性值可以重新修改。 4、final static 表示全局不可更改,常用来修饰配置信息等

10、单例模式

场景:比如无论计算机连接多少打印机,但同时只有一台打印机在工作。

应用场景:如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

​ 1.创建对象时占用资源过多,但同时有需要用到该类对象 2.对系统内资源要求统一读写,如读写配置信息 3.当多个实例存在可能引起程序逻辑错误,如号码生成器

目的:使得类的一个对象成为该系统中的唯一实例。

定义:一个类有且仅有一个实例,并且自行实例化向整个系统提供。

设计要点: 1、某个类只能有一个实例 2、必须自行创建实例 3、必须自行向整个系统提供这个实例

实现: 1、只提供 私有 的构造方法 2、必须在类中创建该类的 静态 私有对象 3、在类中提供一个 静态 的公有方法用于创建、获取静态私有对象

代码实现方案: 1、饿汉式:对象创建过程中实例化 2、懒汉式:静态公有方法中实例化

饿汉式

创建对象实例的时候直接初始化

1.创建私有构造 2.创建该类型的私有静态实例 3.创建公有静态方法返回静态实例对象

public class SingletonOne {
	//1、创建类中私有构造
	private SingletonOne() {
		
	}
	//2、创建该类型的私有实例
	private static SingletonOne instance=new SingletonOne();
	//3、创建公有静态方法
	public static SingletonOne getInstance() {
		return instance;
	}
}

​ 空间换时间。进行加载的时候,就已然完成了对实例化的操作,此时无论你是否使用,这个实例都将存在在内存中。饿汉式因为在类加载时已经完成了对象的实例化创建,所以是线程安全的。

懒汉式

1.创建私有构造方法; 2.创建静态的该类实例对象 3.创建开放的静态方法提供实例对象

​ 时间换空间,类内实例对象创建时并不直接初始化,直到第一次调用get方法时,才完成初始化操作。这使得它存在线程风险。可以通过 1、同步锁 2、双重校验锁 3、静态内部类 4、枚举 解决

public class SingletonTwo {
	//1、创建私有构造方法
	private SingletonTwo() {
		
	}
	//2、创建静态的该实例对象
	private static SingletonTwo instance=null;
	//3、创建开放的静态方法提供实例对象
	public static SingletonTwo getInstance() {
		if(instance==null)		//
			instance=new SingletonTwo();
		return instance;
	}
}

优缺点

优点: 1.在内存中只有一个对象,节省内存空间 2.避免频繁的创建销毁对象,提高性能 3.避免对共享资源的多重占用。

缺点: 1.扩展比较困难 2.如果实例化后的对象长期不利用,系统将默认为垃圾进行回收,造成对象状态丢失。

11、多态

多态: 意味着允许不同类的对象对同一消息做出不同的响应。

分类:1)编译时多态(也叫设计时多态,举例如方法重载) 2)运行时多态(程序运行时决定调用哪个方法) java中的多态大多指运行时多态。多态的实现有两个必要条件: 1 、满足继承关系 2 、父类引用指向子类对象

1)向上转型

父类引用指向子类具体实例:向上转型(隐式转型、自动转型)

可以调用子类重写父类的方法以及父类派生的方法,无法调用子类特有的方法。

2)向下转型

向下转型(也称强制类型转换):子类引用指向父类对象。此处必须强制转换,可以调用子类特有的方法

instanceof :判断左边的对象是否满足右边类的实例特征,是 返回true,否则返回false。

总结:在父类当中使用static 关键字修饰的方法不能被子类所重写。加上@Override注解会报错。 父类引用指向子类实例,可以调用子类重写的方法以及父类派生的方法,无法调用子类独有的方法。 注意:父类中的静态方法无法被子类重写,所以向上转型之后,只能调用到父类原有的静态方法。

3)抽象类

java中使用抽象类限制实例化

abstract 修饰类 (抽象类)不能直接实例化,但是可以通过让子类向上转型,父类引用指向子类实例间接实例化。可以达到在编译期间提示程序员不要实例化一些没有意义的类,真正干活的有意义的是子类的实例对象。

注: public 与 abstract 可以互换,但是却不能 与class关键字相互换位。

使用规则:

1、abstract 定义抽象类

2、抽象类不能直接被实例化,只能被继承,可以通过向上转型的方式完成实例化对象

3、abstract 在父类中定义抽象方法,不需要关心其具体实现,定义时语法上不允许其包含方法体,参数列表后要加分号。子类必须重写父类的抽象方法,否则编译时会报错,除非子类也是抽象类

4、包含抽象方法的类一定是抽象类。

5、一个抽象方法必须定义在抽象类中,而抽象类可以没有抽象方法。static、final、private 不能与abstract 并存

4)接口

场景:如何解决一个类型中需要兼容多种类型特征的问题,以及多个不同类型具有相同特征的问题呢?

定义接口: public interface+接口名,成员方法不能有方法体

调用接口: 类名+implements+接口名,必须重写接口里的方法

接口定义了某一批类所需要遵守的规范 接口不关心这些类的内部数据,也不关心这些类里的方法的实现细节,它只规定这些类里必须提供某些方法。

接口访问修饰符包括:public、默认 接口中方法的访问修饰符默认为public

接口当中抽象方法可以不写abstract关键字。

当一个类实现接口的时候,需要去实现接口中的所有抽象方法,否则需要将该类设置为抽象类。

接口可以实现继承,并且可以继承多个父接口。

接口中定义的都是常量,它们默认public static final,必须在初始化时赋值。使用接口名.常量去访问接口中的常量。注意:如果实现类中存在与接口中同名的常量,当用接口的引用指向实现类时,接口引用访问到的依然是接口中的常量。


​ 如果接口A中有一个public访问权限的静态变量a。按照java的语义,我们可以不通过实现接口的对象来访问变量a,通过A.a = xxx;就可以改变接口中的变量a的值了。正如抽象类中是可以这样做的,那么实现接口A的所有对象也都会自动拥有这一改变后的a的值了,也就是说一个地方改变了a,所有这些对象中a的值也都跟着变了。这和抽象类有什么区别呢,怎么体现接口更高的抽象级别呢,怎么体现接口提供的统一的协议呢,那还要接口这种抽象来做什么呢?所以接口中不能出现变量,如果有变量,就和接口提供的统一的抽象这种思想是抵触的。所以接口中的属性必然是常量,只能读不能改,这样才能为实现接口的对象提供一个统一的属性。

​ 通俗的讲,你认为是要变化的东西,就放在你自己的实现中,不能放在接口中去,接口只是对一类事物的属性和行为更高层次的抽象。对修改关闭,对扩展(不同的实现implements)开放,接口是对开闭原则的一种体现。

(原文:https://blog.csdn.net/happydecai/article/details/80193062)


JDK1.8为接口提供了: 使用default关键字定义的方法,可以在接口中带有方法体,在实现接口的类的方法中可以不重写该接口提供的方法(可选择性)如果想要在实现类中访问接口的默认成员,需要通过接口名.super.方法名访问。

JDK1.8为接口提供了:static静态方法,也可以在接口中带有方法体,通过 接口名.方法 调用,无法在子类中重写。

实现类 实现接口时重名处理

方法重名:

类实现的多个接口存在重名默认方法、子类实现的接口与父类存在重名方法的处理:

1、多接口中存在同名方法:在继承接口的实现类中会编译报错。解决方法为:在继承接口的实现类中,重写同名的默认方法。此时若用指向 实现类实例 的 接口引用调用该方法,则会调用类中重写的方法。

2、父类与接口中都存在重名的方法:指向子类的父类引用调用时,会默认指向父类中的重名方法,除非子类重写该重名方法。

常量重名:

一个类如果实现若干个接口,而这若干个接口之间有同名的常量的时候,在此类中直接调用同名常量时会报错,即使该类有继承关系的父类当中也含有该同名的变量,依然会报错。 解决此类办法的途径,一是通过接口名.变量的方式访问,二是在该子类中定义同名的属于子类自己的成员属性并初始化,以消除这种错误。

5)内部类

内部类:将一个类定义在另一个类的内部,我们就称这个类为内部类,而包含内部类的类称之为外部类。

好处:内部类隐藏在外部内的里面,更好的实现了信息的隐藏。

内部类的分类: 1 、成员内部类 2 、静态内部类 3 、方法内部类 4 、匿名内部类

1-成员内部类

1、内部类在外部使用时,无法进行直接实例化,需要借由外部类的信息才能完成实例化。

获取内部类的对象实例:

​ 方式1:外部类.内部类 类标识名 = new 外部类().new 内部类()

​ 方法2:外部类实例对象 . new 内部类()

​ 方法3:外部类对象 . 内部类的get方法() 需要在外部类中定义内部类的get方法

2、**关于内部类的访问修饰符可以任意,但是访问内部类的范围会受到影响 **

3、内部类可以直接访问外部类的成员,包括成员属性和方法。内部类和外部类如果出现同名属性,内部类中调用时优先访问内部类中定义的

4、内部类和外部类存在同名成员属性情况下,如果想要访问外部类成员属性,可以使用 外部类 . this . 成员的方式访问。

5、外部类访问内部类的信息,需要通过 内部类实例 . 内部类成员,否则无法直接访问。

6、内部类编译后 .class 文件名命名:外部类$内部类.class

2-静态内部类

1、静态内部类中,只能直接访问外部类的静态成员,如果需要调用非静态成员,只能通过外部类的对象实例

2、静态内部类对象实例时,可以不依赖于外部类对象(不需要先new一个外部类对象,直接用类)

3、可以通过 外部类 . 内部类 . 静态成员 访问内部类中的静态成员

4、当内部类属性于外部类属性同名的时候,默认直接调用内部类中的成员

5、如果需要访问外部类当中的的静态属性,则可以通过 外部类 . 属性 的方式。

6、如果需要访问外部类当中的的非静态属性,则可以通过 new 外部类() . 属性 的方式访问。

3-方法内部类(局部内部类)

1、定义在方法内部,作用范围也在方法内

2、和方法内部成员使用规则一样,class前面不可以添加public、private、protected、static。作为方法里的一个成员,方法内部类的所有动作只能基于这个方法去做。一般使用方法内部类时很少在方法上直接返回类,而是返回调用方法内部的get方法。

3、方法内部类中不能包含静态成员

4、方法内部类中可以包含final、abstract(不推荐)修饰的成员

4-匿名内部类

隐藏名字。适用于:只用到类的一次实例,类在定义后马上用到,给类命名并不会导致代码更容易被理解 的场景。 类 . 方法 ( new 类() { 方法体 } ) 实例对象的同时完成对对象的编写,内存损耗较小。

1、匿名内部类没有类型名称、实例对象名称

2、编译后的文件命名:外部类$数字.class

3、无法使用private\public \protected\abstract\static修饰

4、无法编写构造方法(因为没有类名),可以添加构造代码块

5、匿名内部类不能出现静态成员

6、匿名内部类可以实现接口也可以继承父类,但是不可兼得

三、Java常用工具类

12、异常

1)常见异常

13、包装类

14、字符串

substring() 方法:返回字符串的子字符串。

public String substring(int beginIndex)public String substring(int beginIndex, int endIndex)

beginIndex – 起始索引(包括), 索引从 0 开始。

endIndex – 结束索引(不包括)。

String的不可变性:String对象一旦被创建,则不能修改,是不可变的 所谓的修改其实是创建了新的对象,所指向的内存空间不变。


String s1=“a”; String s2=“a”; s2这个引用指向的是s1在常量池中的“a”。s2=“b”; s2并没有改变原来“a”的值,它指向了一个新的常量。原来的“a”任然占据内存空间,等待被垃圾回收。


15、集合与排序

集合应用场景:

集合框架的体系结构

1)List

List是元素有序并且可以重复的集合,称为序列。 List可以精确的控制每个元素的插入位置,或删除某个位置的元素。 List的两个主要实现类是ArrayList和LinkedList。

ArrayList

ArrayList底层是由数组实现的。 在列表尾部插入或删除数据非常有效,更适合查找和更新元素。ArrayList中的元素可以为null,允许重复值。

ArrayList可以动态增长。

HashSet

HashSet是Set的一个重要实现类,称为哈希集。HashSet中的元素无序并且不可以重复,HashSet中只允许一个null元素,具有良好的存取和查找性能。

Iterator

Set接口、HashSet类中都没有显示元素的get方法,想显示元素要靠 Iterator(迭代器)

Iterator接口可以以统一的方式对各种集合元素进行遍历。

.hasNext() 方法检测集合中是否还有下一个元素,它的返回值是boolean类型。

.next() 方法返回集合中的下一个元素,返回Object类型的对象。

向 HashSet() 中插入重复元素不会报错,因为系统并不会把重复元素插入到集合中。


解答:当调用add(Object)方法时候,首先会调用Object的hashCode方法判断hashCode是否已经存在,如不存在则直接插入元素;如果已存在则调用Object对象的equals()方法判断是否返回true,如果为true则说明元素已经存在,如为false则插入元素。HashSet是借助HashMap来实现的,利用HashMap中Key的唯一性,来保证HashSet中不出现重复值


当Set集合要添加新的元素时,会先隐式调用这个元素的hashCode方法,就能定位到它应该放置的物理位置。如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了;如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了,不相同就散列其它的地址。


2)泛型

在集合中引入泛型之后可以使用增强型for循环遍历集合中的每个元素. 集合为避免数据的不一致性,限制读取时不允许删除。 集合中多条删除,要把它们添加到一个集合当中:

Set<Cat> set1=new HashSet<Cat>();
for(Cat cat:set) {
	if(cat.getMouth()<5){
    	set1.add(cat); 
    }
}
set.removeAll(set1);

3)Map

Map中的数据是以键值对(key-value)的形式存储的。key-value以Entry类型的对象实例存在。可以通过key值快速地查找value值。 一个映射不能包含重复的键。 每个键最多只能映射到一个值。

HashMap

基于哈希表的Map接口的实现。允许null值和null键。key值不允许重复。 HashMap中的Entry对象是无序排列的。

4)Comparator和Comparable

Comparator接口

强行对某个对象进行整体排序的比较函数 可以将Comparator传递给sort方法(如Collections.sort或Arrays.sort) int compare(T o1,T o2) 比较用来排序的两个参数。

Comparable接口

此接口强行实现它的每个类的对象进行整体排序 这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。

对于集合,通过调用Collections.sort方法进行排序;对于数组,通过调用Arrays.sort方法进行排序

int comparaTo(T o) 方法。

相关文章

    暂无相关文章

用户点评