JAVA基础接口集合框架
接口
--------------------------------------------------------------------------------
一、接口(是一种规范)
1.接口名/接口文件与类类似,也是用.java文件编写
2.关键字 interface 接口名命名规范与类名相同 习惯上可以使用I开头表示
3. 接口额访问修饰符只能使用public和default修饰不能使用private和protected
在接口中默认缺省为public
4.接口中的所有属性只能为公开的静态的常量
而且public/static/final都可省略
5.接口中的所有方法必须为公共的抽象方法 且抽象方法中的abstract/public可省略
省略后依然是公开的
--------------------------------------------------------------------------------
二、实现类实现接口
1.一个类实现接口使用Implements关键字
实现类实现一个接口必须重写接口中的所有抽象方法 除非是抽象类
2.一个类可以实现多个接口 多个接口之间用逗号间隔
3.接口的引用可以指向其实现类的对象。类似于父类引用指向子类对象
因此可以使用接口实现多态
--------------------------------------------------------------------------------
三、接口继承接口
1.接口可以继承接口,使用extends关键字;接口的继承与类相同
2.接口可以多继承 使用多个父接口,使用逗号分割,
子接口继承父接口将拥有父接口的所有抽象方法
--------------------------------------------------------------------------------
四、接口的优点
1.可以被多继承
2.设计和实现完全分离
3.更自然的使用多肽
4.更容易搭建程序框架
5.更容易更换实现
--------------------------------------------------------------------------------
五、接口和抽象类的区别
1.本质区别 关键字不同 class interface
子类继承抽象类 子类必须与父类是一类事物 必须符合"is a"关系
例如Chinese are peope
接口只是对功能的扩展,多个实现类实现接口时
并不要求所有的抽象类是一类事物
接口符合"like a"关系,理解为X具备一个X功能
例 人\狗 都有吃饭功能 都可以实现吃饭接口
但是两者吃饭功能不能从同一父类中继承
2.抽象类是类 接口是规范
3.接口可继承接口 并可多继承接口可多实现 但类只能单根继承
4.接口只能做方法声明,抽象类中可以做方法声明,也可以做方法实现
5.抽象类能够保证实现的层次关系,而借口则是能够更有效地分离行为和实现
6.抽象类可以有自己属性 接口智能有静态常量
7.接口中智能有抽象方法,抽象类中可以有抽象方法
集合框架
对常用的数据结构和算法做一些规范(接口)和实现(具体实现接口的类)
--------------------------------------------------------------------------------
一、集合框架的接口
Collection:存储一组不唯一 无序的对象
List:存储一组不唯一 有序
Set存储一组唯一 无序的对象
Map存储一组键值对象,提供key到value的映射(key不能重复)
--------------------------------------------------------------------------------
二、List 常用方法 (ArraysList:长度可变的数组)
【List接口】
1、常用方法:
① add():在列表的最后添加元素;
② add(int index,E element):在列表的指定位置插入元素;
③ size():返回当前列表的元素个数;
④ get(int index):返回下标为index的元素。
如果没有泛型约束,返回Object类型,需要强转;如果有泛型约束,直接返回泛型类型,无需强转。
⑤ clear():清除列表中的所有数据
isEmpty():检测列表是否为空
⑥ contains():传入一个对象,检测列表中是否包含该对象。
如果传入的是String和基本数据类型,可以直接比对
如果传入的是实体类,则默认只比对两个对象的地址。因此,需要在实体类重写equals()方法;
Tips:
String s = "123";
="123".equals(s);//这个顺序可以防止空指针
⑦ indexOf():传入一个对象,返回该对象在列表中首次出现的地址。
lastIdexOf():传入一个对象,返回该对象在列表中最后一次出现的地址。
⑧remove():传入一个下标,或者一个对象,删除指定元素;
如果传入下标,返回被删除的对象,如果下标大于size(),会报下标越界异常;
如果传入对象,则要求重写equals方法,返回true或false表示删除是否成功
⑨set(index, obj):用新传入的对象,将指定位置的元素替换掉;
返回被替换掉的元素对象。
⑩subList(1,3):截取一个子列表,返回List类型
⑪toArray() 将列表转为数组 返回一个object类型的数据
--------------------------------------------------------------------------------
三、使用iterator迭代器遍历列表
1.使用列表调用 .iterator()返回一个迭代器对象
2.使用迭代器对象调用.hasNext()判断是否有下一条数据
3.使用迭代器对象调用.next()取出下一条数据
--------------------------------------------------------------------------------
四、ArrayList LinkedList
1.ArrayList 实现一个长度可变的数组,在内存空间中开辟一串连续的空间,
与数组的区别在于长度可以随意的改变,
这只能存储结构在寻欢遍历和随机访问元素的速度比较快
2.LinkedList 使用链表结构存储数据,再插入和删除元素时速度非常快
特有方法
①addFirst():开头插入元素
addLast():结尾插入元素
②removeFirst() 删除第一个元素,并返回被删除的元素
removeLast()删除最后一个元素,并返回被删除的元素
③getFirst()返回列表的第一个元素 不删除
getLast()返回列表的最后一个元素 不删除
Set接口
1.常用方法:与List接口基本相同
但是,由于set接口中的元素是无序的,因此没有与下标相关的方法
2.Set接口的特点:唯一,无序
取出set方法
使用for each遍历
使用迭代器遍历
3.HashSet 底层调用HashMap的方法 传入数据后 根据数据的hashcode进行散列运算
得到一个散列值后在进行运算,确定数据在序列中存储的位置
4.HashSet如何确定一个对象是否相等
先判断对象的hashcode()是否相等 若不等 肯定不是一个对象
若相等 继续判断equals()方法;
重写equals()方法
所以使用HashSet存储实体对象时,必须重写对象的hashCode() 和equals()两个方法
LinkedHashSet 在HashSet的基础上,新增一个链表
用链表来记录HashSet中元素放入的顺序,因此使用迭代器遍历时,可以按照放入的顺序依次
读出元素
comparator 需要单独一个比较类进行实现,重写compare()的方法,实例化TreeSet的对象,需要哦转入这个比较类的对象
Map
1.Map 接口特点 以键值对的形式存储数据,以键取值,键不能重复值可以重复
2.put(key value) 最后追加一个键值
get 通过键取值
clear清除所有数据
HashMap 与Hashtable区别
1.后者线程安全 前者不安全
2.后者键不能为null 前者可以
HashMap和Hashtable的区别
两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全。Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高一些,我们平时使用时若无特殊需求建议使用HashMap,在多线程环境下若使用HashMap需要使用Collections.synchronizedMap()方法来获取一个线程安全的集合(Collections.synchronizedMap()实现原理是Collections定义了一个SynchronizedMap的内部类,这个类实现了Map接口,在调用方法时使用synchronized来保证线程同步,当然了实际上操作的还是我们传入的HashMap实例,简单的说就是Collections.synchronizedMap()方法帮我们在操作HashMap时自动添加了synchronized来实现线程同步,类似的其它Collections.synchronizedXX方法也是类似原理。
HashMap可以使用null作为key,不过建议还是尽量避免这样使用。HashMap以null作为key时,总是存储在table数组的第一个节点上。而Hashtable则不允许null作为key。
HashMap继承了AbstractMap,HashTable继承Dictionary抽象类,两者均实现Map接口。
HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。
HashMap扩容时是当前容量翻倍即:capacity*2,Hashtable扩容时是容量翻倍+1即:capacity*2+1。
HashMap和Hashtable的底层实现都是数组+链表结构实现。
两者计算hash的方法不同:
Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模:
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸:
static int hash(int h) {
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
static int indexFor(int h, int length) {
return h & (length-1);
}
在HashMap 中,null 可以作为键,这样的键只有一个;可以有一个或多个键所对
应的值为null。当get()方法返回null 值时,既可以表示HashMap 中没有该键,也可
以表示该键所对应的值为null。因此,在HashMap 中不能用get()方法来判断HashM
ap 中是否存在某个键,而应该用containsKey()方法来判断。Hashtable 的键值都不能
为null,所以可以用get()方法来判断是否含有某个键。
LinkedHashMap
可以使用链表 计入数据放入的次序
Collections是Java中专门用于操作的集合工具类
Collection是一个接口
sort方法 对 集合中的数据进行排序
如果集合存储的是一个实体对象那么
1 实体类实现Comparable接口,并重写CompareTo方法
2.在sort的第二个参数,传入比较器,比较器需实现comparable接口,并重写compare方法
【泛型】
1、泛型就是“参数化类型”。在定义类型时,不将类型定死。而是采用泛型参数的形式进行定义。调用时传入具体的泛型参数。
【泛型类的特点】
在声明类的时候,进行泛型约束,这样的类叫泛型类。
class Test<T>{
//<T>可以理解为泛型声明时的形参,可以用任何字母代替。常用T N E
//在泛型类中,T就可以当做特殊的数据类型进行使用
private T arg;
}
//泛型调用时,需要将实际的数据类型进行传入
Test<String> test1 = new Test<String> ("姜浩真帅!");
Test<Integer> test2 = new Test<Integer>(123);
1、泛型只在编译阶段生效。同一个类通过不同泛型拿到的对象,使用getClass()判断是属于同一个类的。
System.ou.println(test1.getClass() == test2.getClass());
//取到的test1的类为Test类,不是Test<T>类
2、同一个类,通过不同泛型拿到的对象,相互不兼容。不能互相赋值。
test2 = test1;//test1与test2不兼容
3.泛型类 在实例化的时候,可以不传入泛型,类中的数据类型,在赋值的时候传入的变量类型为空
4.实例化泛型时,智能传入类名,可以是系统类也可以是自定义实体类
泛型通配符上边界,使用?extends类名表示通配符只支持指定类的子类
Test<?extends Number>testS = new Test<Number>();
泛型通配符下边界,使用?super类名,表示通配符只支持指定类及其超类;
泛型的接口
1.声明
interface inter<T>{
void Test(T t );
}
2.实现类 如果实现泛型接口,那么不能直接使用接口的泛型,那么需要重新声明
class Test3<T> implements inter<T>{
@Override
public void Test(T t){}
}
3.如果实现类,不想作为泛型类,那么,可以在实现接口时,直接给接口的泛型赋值
class Test3 implements inter<String>{
@Override
public void Test(String t){}
}
泛型方法
1.不一定在泛型类中 可以独立于泛型类在任何类中都可以单独使用
class Test{
public static <T> void test(T t){}
}
调用 Test.test("String");
2.使用泛型方法可以实现可变参数的方法
class Test{
/使用...表示可以接受n个任意类型的参数也可以是数组
public static <T> void test(T......t){}
}
通用:Test.test("String","String2",123,true)
3.只有在方法中声明了<T>的方法 才能是泛型方法
而如果在方法中,使用额类的泛型 则不是泛型方法
注意:
静态方法不能使用类的泛型
智能将静态方法单独声明为泛型方法
【Random类】
【Random类】
取随机数。
两种构造:
①空参构造
②传入一个种子数:只要种子数相同,那么在相同次数取到的随机数肯定相同。这是伪随机数。可以传入当前的时间戳:System.currentTimeMillis();
nextInt():随机获得一个整数;
nextInt(n):随机获得从0-n的随机数,含0不含n;
【单例模式】
单例模式:确保一个类,只能产生一个实例。
设计思路:
①将构造函数私有化。确保类外部,不能使用new关键字自行创建对象。
②在类内部实例化一个对象,并通过静态方法返回。
Enum类】
枚举类,是一种特殊的类。
里面的值,全部都是静态常量。每一个枚举值,都相当于一个本类对象,只不过,对象的值都是对象名。
【枚举类的声明】
【Date类】
位于Java.util包下
data空参构造:取到当前时间
data全参构造:传入一个long类型的时间戳,取到指定时间。
date.getTime():取到一个时间的时间戳:从0时区,1970/1/1 0:0:0到当前时间的毫秒数
setTime():传入一个长整型,重新设置date的时间
compareTo():前面>参数 返回1 前面<参数 返回-1 前面= 参数 返回0
equals():比对两个时间是否相等。
before():检测一个时间是不是在指定时间之前
after():检测一个时间是不是在指定时间之后
【SimpleDateFormat】
位于Java.text包下,对日期进行格式化
实例化对象时,传入格式化参数,用字母代表对应部分
字母 日期或时间元素 表示 示例
y 年 Year 1996; 96
M 年中的月份 Month July; Jul; 07
d 月份中的天数 Number 10
E 星期中的天数 Text Tuesday; Tue
H 一天中的小时数(0-23) Number 0
h am/pm 中的小时数(1-12) Number 12
m 小时中的分钟数 Number 30
s 分钟中的秒数 Number 55
format():用于传入一个Date类型的参数,并返回格式化之后的字符串
parse():将字符串格式的时间,转成Date类型。要求传入的字符串格式,必须与实例化时的模式,保持完全一致
toPattern():返回当前格式化的模式字符串。
【Calender类】
Calendar日历类是一个抽象类,不能直接通过new拿到对象,必须使用Calendar.getInstance();拿到
getTime 返回一个日期对象
get根据calendar提供的常量,获得指定字段