目录
集合!!重点
集合的长度是可变的,数组的长度是不可变的。集合提供了丰富的API。
collection集合:
list set 队列
ArrayList最常用 LinkedList Vector
HashSet最常用 TreeSet LinkedHashSet
数组回顾 int[] arr={1,8,9} int[] arr=new int[3] int[] arr=new int[]{1,2,5}
java数据类型 2
基本数据类型 引用数据类型
byte short int long float double boolean char
数组 类 接口
1. 常用API
- 添加相关的方法
add(E e) 确保此 collection 包含指定的元素(可选操作)
addAll(Collection<? extends E> c)
将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
- 删除相关的方法
clear() 移除此 collection 中的所有元素(可选操作)。
remove(Object o) 从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
removeAll(Collection<?> c) 移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
- 判断相关的方法
contains(Object o) 如果此 collection 包含指定的元素,则返回 true。
containsAll(Collection<?> c) 如果此 collection 包含指定 collection 中的所有元素,则返回 true。
isEmpty() 如果此 collection 不包含元素,则返回 true。
- 数组的转换相关方法
toArray() 返回包含此 collection 中所有元素的数组。
2. List集合
1. 概念
List是有序的集合,就像我们的数组一样。我们可以把list理解为是一个长度可变的数组,而且提供了丰富的api。List的集合底层就是数组。
public static void main(String[] args) {
//创建一个list的集合
List list = new ArrayList();
//向末尾添加元素
list.add("吴用"); //0
list.add("刘唐"); //1
list.add("宋江"); //2
System.out.println(list);
//我们在1处的索引位置来插入元素,我们插入一个元素的话,改索引后面的元素都会向后移动一位
list.add(1, "晁盖");
System.out.println(list);
//创建一个集合
List list1 = new ArrayList();
list1.add("阮小五");
list1.add("阮小二");
list1.add("阮小⑦");
list.addAll(list1);
System.out.println(list);
}
public static void main(String[] args) {
//创建一个list的集合
List list = new ArrayList();
//向末尾添加元素
list.add("吴用"); //0
list.add("刘唐"); //1
list.add("宋江"); //2
System.out.println(list);
//我们在1处的索引位置来插入元素,我们插入一个元素的话,改索引后面的元素都会向后移动一位
list.add(1, "晁盖");
System.out.println(list);
//创建一个集合
List list1 = new ArrayList();
list1.add("阮小五");
list1.add("阮小二");
list1.add("阮小⑦");
list.addAll(list1);
System.out.println(list);
}
2. List的迭代器
iterator() 返回在此 collection 的元素上进行迭代的迭代器。
迭代器也是一个一个遍历的,不用for循环
通过ListIterator的方式遍历:
ListIterator listIterator = list.listIterator();
while(listIterator.hasNext()){//判断是否有下一个值
//获得迭代的元素
String str = (String) listIterator.next();//取下一个值
if("刘唐".equals(str)){
//我们不能在一边遍历的时候一边操作集合,这样有多线程的并发问题
//list.add("白胜");
//迭代器可以给我们提供了一个add方法让我们避免并发问题,但是添加的时候本次遍历不生效
listIterator.add("白胜");//这次遍历没有
}
System.out.println(str);
}
System.out.println(list);
我们可以使用for循环来动态的遍历List集合 普通for循环不支持并发操作。
//int size = list.size();
//for循环对list的变量, 我们可以使用动态获得集合的长度的方式来遍历
for (int i = 0; i < list.size(); i++) {
//根据索引来获得对应的元素
String str = (String) list.get(i);
if("刘唐".equals(str)){
list.add("阮小五");
}
System.out.println(str);
}
3.List集合特点:
- 有序集合
- 元素可以重复 有索引,根据索引区分
- 长度可变
- 底层实现为数组
4. ArrayList
ArrayList的底层是数组的原理。
ArrayList中的元素是可以重复
是有序的集合,长度不固定。
不是线程安全的。-- 性能高
效率高。
长度的变化:
ArrayList在添加数据的时候初始的长度是10,后续会以5个长度来扩充集合的长度。
ArrayList不是线程安全的集合,适合不要求线程安全的需求来实现。
好处是性能高。
缺点就是线程不安全,可能带来数据不准确。
如果线程要是同步的话,性能就会变低。 适合查
并发
同步 多线程
卫生间,独立的,一个,单线程
公共卫生间,多线程。效率高
5. LinkedList
Linked也不是线程安全的。
- 底层结构是链表实现
- 适合做增删改的业务场景
- 线程不安全
- 有序集合但是更适合增删改
链表:储存了元素和前后的地址
LinkedList是链表为原理,添加修改删除的性能高。
栈:先进后出
队列:先进先出
6.Vector
- Vector底层也是数组。
- 线程安全,支持多线程并发访问
- 可以存储任意类型对象,包括null
- 自定扩容,扩容机制是增量为当前容量的一半
public static void main(String[] args) {
Vector v = new Vector();
v.add("宋江");
v.add("晁盖");
v.add("刘唐");
System.out.println(v);
Object o = v.get(1);
//Object o1 = v.elementAt(1);
System.out.println(o);
System.out.println("--------------分割线-----------------");
for (int i = 0; i < v.size(); i++) {
Object o1 = v.get(i);
System.out.println(o1);
}
System.out.println("--------------分割线-----------------");
Enumeration elements = v.elements();//枚举
while(elements.hasMoreElements()){
Object o1 = elements.nextElement();//获取枚举对象
System.out.println(o1);
}
}
7. 泛型
泛型就是在集合中指定存储的数据类型,而且只能存储这种类型,在List<类型>必须要指定, ArrayList<>可以指定也可以不指定。基本数据类不能作为泛型。
public static void main(String[] args) {
//定义一个集合里面指定只能存储一种数据类型
List<String> list = new ArrayList<>();
}
迭代器:
public static void main(String[] args) {
//定义一个集合里面指定只能存储一种数据类型
List<String> list = new ArrayList<>();
//调用集合
list.add("亮亮");
list.add("腻腻");
list.add("腻腻1");
list.add("腻腻2");
list.add("腻腻3");
//创建一个迭代器对象
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()){
//获得到String类型
String next = iterator.next();
System.out.println(next);
}
}
7.2 自定义的泛型
在自定义泛型时
语法:
class/interface 类名/接口名 <T>{
}
T只是泛型的一个标准,使用什么字符都可以,但是都要大写,不要使用特殊字符,建议用T。
自定义泛型类
public class GenericTest<T> {
//定义一个泛型的属性
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
测试
public static void main(String[] args) {
GenericTest<String> gt = new GenericTest<>();
gt.setT("哈哈");
//获得对应的泛型的结果
String t = gt.getT();
//指定泛型是Integer类型
GenericTest<Integer> gt1 = new GenericTest<>();
gt1.setT(1);
Integer t1 = gt1.getT();
//指定泛型是Integer类型的数组
GenericTest<Integer[]> gt2 = new GenericTest<>();
gt2.setT(new Integer[]{1, 2, 4});
Integer[] t2 = gt2.getT();
//测试2个泛型
GenericTest1<String, Integer> gtt1 = new GenericTest1<>("亮哥", 30);
GenericTest1<String, Date> gtt2 = new GenericTest1<>("亮哥", new Date());
}
3. Set
1. 概念
Set:
Set是Collection的子接口
无序性,无重复的元素
Set是个接口,不能直接创建对象,需要实现类来创建对象
Set的实现类是HashSet, linkedhashset, treeset
2. Hashset:
特点:
- 1.元素唯一性
- 2.无序性
- 3.允许null存在一个
- 4.不是线程安全(效率高)
- 5,底层实现是数据结构是哈希表(哈希表依赖的两个方法:hashcode()和equals()方法)
(一般规则:对象的equals是true的话,hashcode需要相同,但是hashcode相同的对象不一定equals相同,这就是所谓的冲突现象,但是有不同的解决方法。你的hashCode()方法设计的好就会减少冲突。)
public static void main(String[] args) {
/**
* set是无序的
* set的元素是不可重复的,如果重复了就会自动的去掉
* set只能有一个null
*/
Set<String> set = new HashSet<>();
//给set添加元素
set.add("董卓");
set.add("张让");
set.add("何进");
set.add("李肃");
set.add(null);
System.out.println(set);
}
添加的时候回去判断比对有没有一样的,如果有一样的,就会覆盖掉。
我们对set的唯一性深究一下
如果对象的hash值和equals都相等那么就是重复的对象。
equals()作用:
每个类都有这个方法(不仅是字符串类)都是集成object类,默认和==一样比较指向是否相同。
- 字符串中对这个方法进行了重写,仅比较值。
- 重写equals还需要重写 hashcode(),相当于身份证号码。 因为 hashmap 的使用需要这两个方法配合。
面试题还会问 如何打配合,hashmap存放数据原理。
- 基本数据类型 只能用==号比较,比较的就是值,它里面没有equals方法。
- 引用数据类型 用==比较的是地址。用equals不一定比较的是值,因为根类Object类比较的是地址。实现类重写不一定写的比较的就是值。
类属于引用数据类型
- 字符串重写:
- 所有类的根类object:
所有类都继承object,在不改写equals方法时,比较的是地址。
但是每写一个实现类,他都会重写equals.
public static void main(String[] args) {
//创建一个存储Person对象的集合
Set<Person> set = new HashSet<>();
set.add(new Person("孔明", 26));
set.add(new Person("刘备", 28));
set.add(new Person("关羽", 27));
set.add(new Person("张飞", 25));
set.add(new Person("张飞", 25));
System.out.println(set);
}
如果没有重写,比较的是地址,就不一样。因为是new出来的。
3. LinkedHashSet
特点:
1.元素唯一性
2.有序的
3.允许null存在一个(因为不能重复)
4.不是线程安全(效率高)
5,底层数据结构由链表和哈希表组成。
LinkedHashSet和HashSet来对比就是多了一个顺序。应用的不多。
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<>();
set.add("董卓");
set.add("张让");
set.add("何进");
set.add("李肃");
set.add(null);
System.out.println(set);
}
4. TreeSet
4.1 排序比较
放在TreeSet里的类都必须实现Comparable接口
类如果要实现比较的规则都会实现Comparable接口。
String对CompareTo的实现
TreeSet的特点
特点:
1.元素唯一性
2.可自定义排序的(两种 Comparable接口 自己定义比较类实现Comparator比较器接口)
3.不允许null存在
4.不是线程安全
5,treeset集合中的包装类都必须实现Comparable接口。
6,底层数据结构是红黑树。(是一种自平衡的二叉树)
字符串已经实现了Comparable接口。
@Override
public int compareTo(Student o) {
//做年龄的差
int flag = this.age - o.age;
if(flag == 0){
flag = this.name.compareTo(o.name);
}
return flag;
}