java基础-集合-day14
1. 数据结构 算法
算法:解决问题的步骤
例如 1+2+3+...+100
50*(1+100)=5050
算法优劣的度量:时间复杂度 空间复杂度
数据结构:
计算机中如何高效的管理数据
逻辑结构:
思想层面的数据存放编排结构
物理结构:
计算机内存或者硬盘上具体的存放逻辑
以线性表这个逻辑结构来举例:两种物理结构(实现方式)
- 紧密结构
线性表逻辑结构,对应的真实结构如果是跳转结构---》典型就是 链表:
优点:删除元素,插入元素效率高
缺点:查询元素效率低
可以 通过第一个索引的位置计算出其他的元素索引位置
- 链式结构 --跳转结构
单项链表 双向链表 循环链表 具体的可以baidu
2. 本章的重点 集合
集合:存放数据 组织数据的容器
增提分成2大阵营:一个一个存储 一对一对的存储
3. collections
Collection接口的常用方法:
增加:add(E e) addAll(Collection<? extends E> c)
删除:clear() remove(Object o)
修改:
查看:iterator() size()
判断:contains(Object o) equals(Object o) isEmpty()
package com.msb.coll01;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 9:41
* @Description: com.msb.coll01
* @version: 1.0
*/
public class Test01 {
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(18);
col.add(12);
col.add(11);
col.add(17);
System.out.println(col);
List li = Arrays.asList(new Integer[]{1, 2, 3, 4});
col.addAll(li);
System.out.println(col);
//col.clear();
System.out.println(col.size());
System.out.println(col.isEmpty());
boolean isRemove = col.remove(12);
System.out.println(col);
System.out.println(isRemove);
Collection col1 = new ArrayList();
col1.add(18);
col1.add(12);
col1.add(11);
col1.add(17);
Collection col2 = new ArrayList();
col2.add(18);
col2.add(12);
col2.add(11);
col2.add(17);
System.out.println(col2.equals(col1));
System.out.println(col2.contains(12));
}
}
遍历:
1.普通for
2. 增强for
3. iter
迭代器的原理:
hasNext 则执行next方法
next方法:获取当前的元素 并将“指针”下移
package com.msb.coll01;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 9:48
* @Description: com.msb.coll01
* @version: 1.0
*/
public class Test02 {
public static void main(String[] args) {
Collection col = new ArrayList();
col.add(18);
col.add(12);
col.add(11);
col.add(17);
col.add("abc");
col.add(9.8);
// 1.
// for (int i = 0; i < col.size(); i++) {
// System.out.println(col.);;
// }
// 2.
for (Object o : col) {
System.out.println(o);
}
//3.
Iterator it = col.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
4. list
List接口中常用方法:
增加:add(int index, E element)
删除:remove(int index) remove(Object o)
修改:set(int index, E element)
查看:get(int index)
判断:
package com.msb.coll01;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 9:59
* @Description: com.msb.coll01
* @version: 1.0
*/
public class TesList01 {
public static void main(String[] args) {
List list = new ArrayList();
list.add(13);
list.add(17);
list.add(-1);
list.add(2);
list.add("abc");
System.out.println(list);
list.add(3, 66);//插入数据
System.out.println(list);
//list.remove(0);//index 0位置移除元素
System.out.println(list);
System.out.println(list.get(0));
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
for (Object o : list) {
System.out.println(o);
}
Iterator it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
}
}
ArrayList源码分析
transient Object[] elementData 存放数据
private int size; 当前有效数据的个数
容量扩容 确保能放下原色
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
初始开辟的是10个
int newCapacity = oldCapacity + (oldCapacity >> 1);
容量不够进行扩容 新的容量是原来的1.5倍数
oldCapacity >> 1 右移动一位 相当于 除以2
jdk1.8之后
elementData 的初始赋值是空的ArrayList 只有add数据之后才会第一次扩容为10
5. 泛型
【1】什么是泛型(Generic):
泛型就相当于标签
形式:<>
集合容器类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK1.5之前只能把元素类型设计为Object,
JDK1.5之 后使用泛型来解决。因为这个时候除了元素的类型不确定,其他的部分是确定的,例如关于这个元素如何保存,如何管理等是确定的,因此此时把元素的类型设计成一个参数,这个类型参数叫做泛型。
Collection, List, ArrayList 这个就是类型参数,即泛型。
元素的类型设计成一个参数,这个类型参数叫做泛型。
/创建一个ArrayList集合,向这个集合中存入学生的成绩:
//加入泛型的优点:在编译时期就会对类型进行检查,不是泛型对应的类型就不可以添加入这个集合。
package com.msb.generic01;
import java.util.ArrayList;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 10:37
* @Description: com.msb.generic01
* @version: 1.0
*/
public class Test01 {
public static void main(String[] args) {
ArrayList<Integer> al = new ArrayList<>();
al.add(98);
al.add(92);
al.add(78);
// al.add("lili");
for (Integer i : al) {
System.out.println(i);
}
}
}
泛型:<>里面传递的参数 是这个对象的类型 使用的时候才会确定
注意:泛型的类型:都是引用数据类型,不能是基本数据类型
- GenericTest 就是一个泛型类
- <>里面就是一个参数类型,但是这个类型是什么呢?这个类型现在是不确定的,相当于一个占位
- 但是现在确定的是这个类型一定是一个引用数据类型,而不是基本数据类型
package com.msb.generic01;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 10:41
* @Description: com.msb.generic01
* @version: 1.0
*/
public class GenericTest<E> {
int age;
String name;
E sex;
public void a(E n){
}
public void b(E[] m){
}
}
泛型类
package com.msb.generic01;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 10:41
* @Description: com.msb.generic01
* @version: 1.0
*/
public class GenericTest<E> {
int age;
String name;
E sex;
public void a(E n){
}
public void b(E[] m){
}
}
class Test{
public static void main(String[] args) {
//实例化的时候不指定泛型
GenericTest gt1 = new GenericTest();
gt1.a("abc");
gt1.a(17);
gt1.a(3.14);
gt1.b(new String[] {"a", "b", "c"});
//指定泛型
GenericTest<String> gt2 = new GenericTest<>();
gt2.sex = "男";
gt2.a("abc");
gt2.b(new String[]{"abc", "123"});
}
}
泛型方法:
- 1.什么是泛型方法:
- 不是带泛型的方法就是泛型方法
- 泛型方法有要求:这个方法的泛型的参数类型要和当前的类的泛型无关
- 换个角度:
- 泛型方法对应的那个泛型参数类型 和 当前所在的这个类 是否是泛型类,泛型是啥 无关
- 2.泛型方法定义的时候,前面要加上
原因:如果不加的话,会把T当做一种数据类型,然而代码中没有T类型那么就会报错
- 3.T的类型是在调用方法的时候确定的
package com.msb.generic01;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 10:48
* @Description: com.msb.generic01
* @version: 1.0
*/
public class GenericTest02<E> {
public void a(E e){}//不是泛型方法
public static <T> void b(T t){}//是泛型方法 注意<T>的位置
}
class Demo{
public static void main(String[] args) {
GenericTest02<String> gt = new GenericTest02<>();
gt.a("abc");
//gt.a(123);// 不可以
//b方法的泛型
gt.b(19);
gt.b("abc");
gt.b(true);
}
}
6. 泛型通配符
package com.msb.generic01;
import java.util.ArrayList;
import java.util.List;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 11:02
* @Description: com.msb.generic01
* @version: 1.0
*/
public class Test02 {
public static void main(String[] args) {
List<Object> list1 = new ArrayList<>();
List<String> list2 = new ArrayList<>();
List<Integer> list3 = new ArrayList<>();
List<?> li = null;//?泛型通配符
li = list1;
li = list2;
li = list3;
}
}
方法里面使用泛型通配符
package com.msb.generic01;
import java.util.List;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 11:04
* @Description: com.msb.generic01
* @version: 1.0
*/
public class Test03 {
// public void a(List<Object> li){
//
// }
//
// public void a(List<String> li){
//
// }
public void a(List<?> li){
for (Object o : li) {
System.out.println(o);
}
}
}
使用
class T{
public static void main(String[] args) {
Test03 t = new Test03();
ArrayList<Integer> arr1 = new ArrayList<Integer>();
arr1.add(1);
arr1.add(12);
arr1.add(123);
t.a(arr1);
t.a(new ArrayList<StringList>());
t.a(new ArrayList<ObjectList>());
}
}
泛型受限
package com.msb.generic02;
import java.util.ArrayList;
import java.util.List;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 11:14
* @Description: com.msb.generic02
* @version: 1.0
*/
public class Test {
public static void main(String[] args) {
List<Object> a = new ArrayList<>();
List<Person> b = new ArrayList<>();
List<Student> c = new ArrayList<>();
List<? extends Person> list1 = null;//指定 ?必须是继承Person 相当于?的上限是Person
// list1 = a;
list1 = b;
list1 = c;
List<? super Person> list2 = null;//下限是Person Person之上的才可以
list2 = a;
list2 = b;
// list2 = c;
}
}
7. linkedList
LinkedList常用方法:
增加 addFirst(E e) addLast(E e)
offer(E e) offerFirst(E e) offerLast(E e)
删除 poll()
pollFirst() pollLast() ---》JDK1.6以后新出的方法,提高了代码的健壮性
removeFirst() removeLast()
修改
查看 element()
getFirst() getLast()
indexOf(Object o) lastIndexOf(Object o)
peek()
peekFirst() peekLast()
判断
package com.msb.linkedtest01;
import java.util.Iterator;
import java.util.LinkedList;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 11:24
* @Description: com.msb.linkedtest01
* @version: 1.0
*/
public class Test01 {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("fff");
list.addFirst("ggg");
list.addLast("hh");
list.offer("kk");//添加元素在尾端
list.offerFirst("pp");
list.offerLast("rr");
System.out.println(list);
System.out.println(list.poll());//删除头上的元素并且将元素输出
list.pollFirst();
list.pollLast();
list.removeFirst();
list.removeLast();
list.remove();
System.out.println(list);
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
for (String s : list) {
System.out.println(s);
}
Iterator<String> it = list.iterator();
while (it.hasNext()){
System.out.println(it.next());
}
for(Iterator<String> it1 = list.iterator();it1.hasNext();){
System.out.println(it1.next());//节省内存
}
}
}
8. 模拟linkedList源码 --面试重点
package com.msb.linkedtest01;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 11:35
* @Description: com.msb.linkedtest01
* @version: 1.0
*/
public class MyLinkedList {
Node first;
Node last;
int count;
public MyLinkedList() {
}
public void add(Object o){
if(first==null){
Node n = new Node(null, null, o);
first = n;
last = n;
}else {
Node n = new Node(last, null, o);
last.setNext(n);
last = n;
}
count ++;
}
public int getSize(){
return count;
}
public Object get(int index){
Node n = first;
for (int i = 0; i < index; i++) {
n = n.getNext();
}
return n.getObj();
}
}
class T{
public static void main(String[] args) {
MyLinkedList ml = new MyLinkedList();
ml.add("aa");
ml.add("bb");
ml.add("cc");
System.out.println(ml.getSize());
System.out.println(ml.get(1));
}
}
源码的实现:
package com.msb.linkedtest01;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 14:30
* @Description: com.msb.linkedtest01
* @version: 1.0
*/
public class JackLinkList<E> {
transient int size = 0;
private static class Node<E>{
E item;
Node<E> next;
Node<E> prev;
public Node(Node<E> prev, E item, Node<E> next) {
this.item = item;
this.next = next;
this.prev = prev;
}
}
transient Node<E> first;//链表的首节点
transient Node<E> last;//链表的尾节点
public JackLinkList() {
}
public boolean add(E e){
linkLast(e);
return true;
}
public int size(){
return size;
}
//追加元素
void linkLast(E e){
final Node<E> l = last;
final Node<E> newNode = new Node<E>(l, e, null);
last = newNode;
if(l==null){
first = newNode;//如果是第一个被添加的元素 first指向该节点即可
}else{
l.next = newNode;//如果不是新节点 last的next指向新节点即可
}
size++;
}
public E get(int index){
return node(index).item;
}
//通过index获取元素
Node<E> node(int index){
if(index<(size>>1)){
Node<E> x = first;
for (int i = 0; i < index; i++) {
x = x.next;
}
return x;
}else{
Node<E> x = last;
for (int i = size-1; i >index ; i--) {
x = x.prev;
}
return x;
}
}
}
class T1{
public static void main(String[] args) {
JackLinkList<String> ml = new JackLinkList<>();
ml.add("aa");
ml.add("bb");
ml.add("cc");
System.out.println(ml.size());
System.out.println(ml.get(1));
}
}
这里面用到了 二分法 从前遍历 从后遍历
9. Iterrable
package com.msb.linkedtest01;
import java.util.Iterator;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 15:00
* @Description: com.msb.linkedtest01
* @version: 1.0
*/
public class MyArrayList<E> {
transient Object[] elementData;
private int size;
private class Itr implements Iterator<E>{
int cursor;
int lastRet = 1;
@Override
public boolean hasNext() {
return cursor != size;//只要不相等 都返回true
}
@Override
public E next() {
int i = cursor;
cursor = i + 1;
Object[] elementData = MyArrayList.this.elementData;
return (E)elementData[lastRet=i];
}
}
}
package com.msb.linkedtest01.com;
import java.util.ArrayList;
import java.util.Iterator;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 15:08
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class msb01 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eeee");
Iterator<String> it = list.iterator();//调用迭代方法得到迭代对象
while (it.hasNext()){
if("ccc".equals(it.next())){
//System.out.println(it.next());
list.add("ffff");
}
}
}
}
一边迭代 一边 改变集合对象 则会报错
解决办法iterator方法改成 listIterator方法
package com.msb.linkedtest01.com;
import java.util.ArrayList;
import java.util.ListIterator;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 15:08
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class msb01 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eeee");
ListIterator<String> it = list.listIterator();//调用迭代方法得到迭代对象
while (it.hasNext()){
if("ccc".equals(it.next())){
//System.out.println(it.next());
it.add("ffff");//这里也需要换成it
}
}
System.out.println(it.hasNext());
System.out.println(it.hasPrevious());
while (it.hasPrevious()){
System.out.println(it.previous());
}
while (it.hasNext())
System.out.println(it.next(
));
System.out.println(list);
}
}
10. HashSet
唯一 无序
package com.msb.linkedtest01.com;
import java.util.HashSet;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 15:34
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class TestSet01 {
public static void main(String[] args) {
HashSet<String> hs = new HashSet<>();
hs.add("hello");
hs.add("apple");
hs.add("banana");
hs.add("html");
hs.add("apple");
hs.add("css");
System.out.println(hs.size());
System.out.println(hs);
}
}
package com.msb.linkedtest01.com;
import java.util.HashSet;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 15:35
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class TestSet02 {
public static void main(String[] args) {
HashSet<Integer> hs = new HashSet<>();
System.out.println(hs.add(19));
hs.add(5);
hs.add(20);
System.out.println(hs.add(19));
hs.add(41);
hs.add(0);
System.out.println(hs.size());
System.out.println(hs);
}
}
package com.msb.linkedtest01.com;
import java.util.HashSet;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 15:39
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class TestSet03 {
public static void main(String[] args) {
HashSet<Person> hs = new HashSet<>();
hs.add(new Person(19, "lili"));
hs.add(new Person(20, "lilu"));
hs.add(new Person(18, "feifei"));
hs.add(new Person(19, "lili"));
hs.add(new Person(20, "nana"));
System.out.println(hs.size());//5
System.out.println(hs);
}
}
11. LinkedHashSet
package com.msb.linkedtest01.com;
import java.util.LinkedHashSet;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 15:47
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class TestSet04 {
public static void main(String[] args) {
LinkedHashSet<Integer> hs = new LinkedHashSet<>();
hs.add(5);
hs.add(20);
System.out.println(hs.add(19));
hs.add(51);
hs.add(0);
System.out.println(hs.add(19)); //false 第二次放入 19 失败
System.out.println(hs.size());
System.out.println(hs);//[5, 20, 19, 51, 0] 唯一 有序
}
}
比较器 的使用
a - b > 0 --> a>b
package com.msb.linkedtest01.com;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 15:51
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class Test04 {
public static void main(String[] args) {
double d1 = 3.15;
double d2 = 4.9;
int bol1 = ((Double) d1).compareTo((Double) d2);// -1 d1<d2
System.out.println(bol1);
}
}
package com.msb.linkedtest01.com;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 15:37
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class Person implements Comparable<Person> {
int age;
String name;
double height;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
public int compareTo( Person p) {
// // 按照年龄
// return this.age - p.age;
// // 按照身高
// return ((Double)(this.height)).compareTo((Double)(p.height));
// 按照名字
return (this.name).compareTo(p.name);
}
}
package com.msb.linkedtest01.com;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:00
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class TestCompare01 {
public static void main(String[] args) {
Person p1 = new Person(14, "alili", 188.0);
Person p2 = new Person(15, "blili", 178.0);
System.out.println(p1.compareTo(p2));
}
}
外部比较器
package com.msb.linkedtest01.com;
import java.util.Comparator;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:04
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class BiJiao01 implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.name.compareTo(o2.name);
}
}
package com.msb.linkedtest01.com;
import java.util.Comparator;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:06
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class Bijiao02 implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.age - o2.age;
}
}
package com.msb.linkedtest01.com;
import java.util.Comparator;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:08
* @Description: com.msb.linkedtest01.com
* @version: 1.0
*/
public class TestComparator {
public static void main(String[] args) {
Person p1 = new Person(14, "alili", 188.0);
Person p2 = new Person(15, "blili", 178.0);
Comparator comparator1 = new BiJiao01();//名字
System.out.println(comparator1.compare(p1, p2));
Comparator comparator2 = new Bijiao02();// age
System.out.println(comparator2.compare(p1, p2));
}
}
建议使用外部比较器 多态实现不同方式的比较
12. TreeSet
package com.msb.treeset01;
import java.util.TreeSet;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:33
* @Description: com.msb.treeset01
* @version: 1.0
*/
public class Test10 {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<>();
ts.add(12);
ts.add(3);
ts.add(7);
ts.add(9);
ts.add(3);
ts.add(16);
System.out.println(ts.size());
System.out.println(ts);
}
}
有序 且唯一
原理: 二叉树 --一种逻辑接口--思想 上的结构 --跳转结构
放入元素的时候:
- 比较 小的往左放 大的往右放 相同则不放
package com.msb.treeset01;
import java.util.TreeSet;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:41
* @Description: com.msb.treeset01
* @version: 1.0
*/
public class Test11 {
public static void main(String[] args) {
TreeSet<String> ts = new TreeSet<>();
ts.add("elili");
ts.add("blili");
ts.add("alili");
ts.add("elili");
ts.add("clili");
ts.add("flili");
ts.add("glili");
System.out.println(ts.size());
System.out.println(ts);//[alili, blili, clili, elili, flili, glili]
}
}
自定义类的比较
package com.msb.treeset01;
import java.util.TreeSet;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:46
* @Description: com.msb.treeset01
* @version: 1.0
*/
public class Test2 {
public static void main(String[] args) {
TreeSet<Person> ts = new TreeSet<>();
ts.add(new Person(10, "elili"));
ts.add(new Person(8, "blili"));
ts.add(new Person(4, "alili"));
ts.add(new Person(9, "elili"));
ts.add(new Person(10, "flili"));
ts.add(new Person(1, "dlili"));
System.out.println(ts.size());
System.out.println(ts);
//[Person{age=1, name='dlili'}, Person{age=4, name='alili'}, Person{age=8, name='blili'}, Person{age=9, name='elili'}, Person{age=10, name='elili'}]
}
}
package com.msb.treeset01;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:43
* @Description: com.msb.treeset01
* @version: 1.0
*/
public class Person implements Comparable<Person> {
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
}
public Person(int age, String name) {
this.age = age;
this.name = name;
}
@Override
public int compareTo(Person o) {
return this.getAge() - o.getAge();//根据年龄比较
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
外部比较器
package com.msb.treeset01;
import java.util.Comparator;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:49
* @Description: com.msb.treeset01
* @version: 1.0
*/
public class MyComparator01 implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.getName().compareTo(o2.getName());
}
}
package com.msb.treeset01;
import java.util.Comparator;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:50
* @Description: com.msb.treeset01
* @version: 1.0
*/
public class MyComparator02 implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.getAge() - o2.getAge();
}
}
package com.msb.treeset01;
import java.util.Comparator;
import java.util.TreeSet;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:46
* @Description: com.msb.treeset01
* @version: 1.0
*/
public class Test12 {
public static void main(String[] args) {
// Comparator<Person> com1 = new MyComparator01();
Comparator<Person> com2 = new MyComparator02();
TreeSet<Person> ts = new TreeSet<>(com2);
ts.add(new Person(10, "elili"));
ts.add(new Person(8, "blili"));
ts.add(new Person(4, "alili"));
ts.add(new Person(9, "elili"));
ts.add(new Person(10, "flili"));
ts.add(new Person(1, "dlili"));
System.out.println(ts.size());
System.out.println(ts);
// name 比较
// [Person{age=4, name='alili'}, Person{age=8, name='blili'}, Person{age=1, name='dlili'}, Person{age=10, name='elili'}, Person{age=10, name='flili'}]
// age 比较
// [Person{age=1, name='dlili'}, Person{age=4, name='alili'}, Person{age=8, name='blili'}, Person{age=9, name='elili'}, Person{age=10, name='elili'}]
}
}
使用匿名类
package com.msb.treeset01;
import java.util.Comparator;
import java.util.TreeSet;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 16:46
* @Description: com.msb.treeset01
* @version: 1.0
*/
public class Test13 {
public static void main(String[] args) {
TreeSet<Person> ts = new TreeSet<>(new Comparator<Person>() {
@Override
public int compare(Person o1, Person o2) {
return o1.getName().compareTo(o2.getName());
}
});
ts.add(new Person(10, "elili"));
ts.add(new Person(8, "blili"));
ts.add(new Person(4, "alili"));
ts.add(new Person(9, "elili"));
ts.add(new Person(10, "flili"));
ts.add(new Person(1, "dlili"));
System.out.println(ts.size());
System.out.println(ts);
// name 比较
// [Person{age=4, name='alili'}, Person{age=8, name='blili'}, Person{age=1, name='dlili'}, Person{age=10, name='elili'}, Person{age=10, name='flili'}]
}
}
遍历方式
左 根 右
左 12 16
3 (7和9) 12 16
3 7(9) 12 16
3 7 12 16
13. map
基本接口:
增加:put(K key, V value)
删除:clear() remove(Object key)
修改:
查看:entrySet() get(Object key) keySet() size() values()
判断:containsKey(Object key) containsValue(Object value)
equals(Object o) isEmpty()
遍历有些特殊
package msb.com.map01;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 20:54
* @Description: msb.com.map01
* @version: 1.0
*/
public class Test01 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
System.out.println(map.put("lili", 1010101));
map.put("name", 123456);
map.put("feifei", 23453456);
System.out.println(map.put("lili", 34565677));
System.out.println(map.size());
System.out.println(map);
System.out.println(map.containsKey("lili"));
System.out.println(map.containsValue("34565677"));
Set<String> set = map.keySet();
for (String s : set) {
System.out.println(s);
}
Collection<Integer> col = map.values();
for (Integer integer : col) {
System.out.println(integer);
}
// 遍历
Set<String> set2 = map.keySet();
for (String s : set2) {
System.out.println(map.get(s));
}
Set<Map.Entry<String, Integer>> entries = map.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
System.out.println(entry.getKey()+"-----"+entry.getValue());
}
}
}
14 TreeMap
内部比较器
package msb.com.map01;
import java.util.Objects;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 21:04
* @Description: msb.com.map01
* @version: 1.0
*/
public class Student implements Comparable<Student>{
private int age;
private String name;
private double height;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public Student() {
}
public Student(int age, String name, double height) {
this.age = age;
this.name = name;
this.height = height;
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
", height=" + height +
'}';
}
@Override
public int compareTo(Student o) {
// return this.getAge() - o.getAge();
return this.getName().compareTo(o.getName());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Student)) return false;
Student student = (Student) o;
return getAge() == student.getAge();
}
@Override
public int hashCode() {
return Objects.hash(getAge(), getName(), getHeight());
}
}
package msb.com.map01;
import java.util.HashMap;
import java.util.Map;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 21:07
* @Description: msb.com.map01
* @version: 1.0
*/
public class Test03 {
public static void main(String[] args) {
Map<Student, Integer> map = new HashMap<>();
map.put(new Student(19,"blili",170.5),1001);
map.put(new Student(18,"blili",150.5),1003);
map.put(new Student(19,"alili",180.5),1023);
map.put(new Student(17,"clili",140.5),1671);
map.put(new Student(10,"dlili",160.5),1891);
System.out.println(map);
System.out.println(map.size());
/*
{Student{age=18, name='blili', height=150.5}=1003,
Student{age=17, name='clili', height=140.5}=1671,
Student{age=19, name='blili', height=170.5}=1001,
Student{age=19, name='alili', height=180.5}=1023,
Student{age=10, name='dlili', height=160.5}=1891}
*/
}
}
外部比较器
package msb.com.map01;
import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;
/**
* @Auther: jack.chen
* @Date: 2023/9/24 - 09 - 24 - 21:07
* @Description: msb.com.map01
* @version: 1.0
*/
public class Test04 {
public static void main(String[] args) {
Map<Student, Integer> map = new TreeMap<>(new Comparator<Student>(){
@Override
public int compare(Student o1, Student o2) {
return ((Double)(o1.getHeight())).compareTo((Double)(o2.getHeight()));
}
});
map.put(new Student(19,"blili",170.5),1001);
map.put(new Student(18,"blili",150.5),1003);
map.put(new Student(19,"alili",180.5),1023);
map.put(new Student(17,"clili",140.5),1671);
map.put(new Student(10,"dlili",160.5),1891);
System.out.println(map);
System.out.println(map.size());
}
}
总结:
15. HashMap部分源码
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable{
static final int DEFAULT_INITIAL_CAPACITY = 16;
static final float DEFAULT_LOAD_FACTOR = 0.75f;
transient Entry<K,V>[] table;//主数组,每个元素为Entry类型
transient int size;
int threshold;//数组扩容的界限值,门槛值 16*0.75=12
final float loadFactor;//用来接收装填因子的变量
//构造器
//this(16,0.75f);调用了当前类中的带参构造器
public HashMap() {
this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
}
int capacity = 1;
while (capacity < initialCapacity)
capacity <<= 1;
//【7】给loadFactor赋值,将装填因子0.75赋值给loadFactor
this.loadFactor = loadFactor;
//【8】数组扩容的界限值,门槛值
threshold = (int)Math.min(capacity * loadFactor, MAXIMUM_CAPACITY + 1);
//【9】给table数组赋值,初始化数组长度为16
table = new Entry[capacity];
public V put(K key, V value) {
int hash = hash(key);
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
static int indexFor(int h, int length) {
//其实这个算法就是取模运算:h%length,取模效率不如位运算
//计算元素放入table中的位置
return h & (length-1);
void addEntry(int hash, K key, V value, int bucketIndex) {
//【25】size的大小 大于 16*0.75=12的时候,比如你放入的是第13个,这第13个你打算放在没有元素的位置上的时候
if ((size >= threshold) && (null != table[bucketIndex])) {
//【26】主数组扩容为2倍
resize(2 * table.length);
//【30】重新调整当前元素的hash码
hash = (null != key) ? hash(key) : 0;
//【31】重新计算元素位置
bucketIndex = indexFor(hash, table.length);
}
//【19】将hash,key,value,bucketIndex位置 封装为一个Entry对象:
createEntry(hash, key, value, bucketIndex);
}
void createEntry(int hash, K key, V value, int bucketIndex) {
//【21】获取bucketIndex位置上的元素给e
Entry<K,V> e = table[bucketIndex];
//【22】然后将hash, key, value封装为一个对象,然后next的指向为e (链表的头插法)
//【23】将新的Entry放在table[bucketIndex]的位置上
table[bucketIndex] = new Entry<>(hash, key, value, e);//7上8下
//【24】集合中加入一个元素 size+1
size++;
}
}
16. 主数组table的容量capacity的长度是如何确定的
不断地左移 直到不能扩
17. 计算索引的位置
static int indeFor(int h, int length){
return h&(length-1);
}
&运算:两个1 才返回1
hash=3 0000 0011
legnth 8-1=7 0000 0111
& 0000 0011 -->3
hash=2 0000 0010
legnth 8-1=7 0000 0111
& 0000 0010 -->3
length-1 转成二进制-->所有位上面被1占
hash&(length-1) 输出的就是hash
18 装填因子
如果装填因子是1, 那么数组满了再扩容,可以做到 最大的空间利用率
但是这是一个理想状态,元素不可能完全的均匀分布,很可能就哈西碰撞产生链表了。产生链表的话 查询时间就长了。
--->空间好,时间不好
那么有人说 ,把装填因子搞小一点,0.5, 如果是0.5的话,就浪费空间,但是可以做到 到0.5就扩容 ,然后哈西碰撞就少,
不产生链表的话,那么查询效率很高
--->时间好,空间不好
所以在空间和时间中,
取中间值,平衡这个因素 就取值为 0.75
19 TreeMap底层原理
递归搜寻 放入正确的位置
public class TreeMap<K,V>{
//重要属性:
//外部比较器:
private final Comparator<? super K> comparator;
//树的根节点:
private transient Entry<K,V> root = null;
//集合中元素的数量:
private transient int size = 0;
//空构造器:
public TreeMap() {
comparator = null;//如果使用空构造器,那么底层就不使用外部比较器
}
//有参构造器:
public TreeMap(Comparator<? super K> comparator) {
this.comparator = comparator;//如果使用有参构造器,那么就相当于指定了外部比较器
}
public V put(K key, V value) {//k,V的类型在创建对象的时候确定了
//如果放入的是第一对元素,那么t的值为null
Entry<K,V> t = root;//在放入第二个节点的时候,root已经是根节点了
//如果放入的是第一个元素的话,走入这个if中:
if (t == null) {
//自己跟自己比
compare(key, key); // type (and possibly null) check
//根节点确定为root
root = new Entry<>(key, value, null);
//size值变为1
size = 1;
modCount++;
return null;
}
int cmp;
Entry<K,V> parent;
// split comparator and comparable paths
//将外部比较器赋给cpr:
Comparator<? super K> cpr = comparator;
//cpr不等于null,意味着你刚才创建对象的时候调用了有参构造器,指定了外部比较器
if (cpr != null) {
do {
parent = t;
cmp = cpr.compare(key, t.key);//将元素的key值做比较
//cmp返回的值就是int类型的数据:
//要是这个值《0 =0 》0
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else//cpm==0
//如果key的值一样,那么新的value替换老的value 但是key不变 因为key是唯一的
return t.setValue(value);
} while (t != null);
}
//cpr等于null,意味着你刚才创建对象的时候调用了空构造器,没有指定外部比较器,使用内部比较器
else {
if (key == null)
throw new NullPointerException();
Comparable<? super K> k = (Comparable<? super K>) key;
do {
parent = t;
cmp = k.compareTo(t.key);//将元素的key值做比较
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
Entry<K,V> e = new Entry<>(key, value, parent);
if (cmp < 0)
parent.left = e;
else
parent.right = e;
fixAfterInsertion(e);
size++;//size加1 操作
modCount++;
return null;
}
}
java基础-集合-day14的更多相关文章
- JAVA基础-集合(二)
一.Map整体结构体系 Map是集合的另一大派系,与Collection派系不同的是Map集合是以键值对儿的形式存储在集合的.两个键为映射关系,其中第一个键为主键(主键是唯一的不可重复),第二个键为v ...
- Java基础-集合的嵌套
Java基础-集合的嵌套 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.静态导入 静态导入是在JDK1.5后的新特性,可以减少开发的代码量,但是实际用处是很一般,静态导入的标准 ...
- Java基础——集合框架
Java的集合框架是Java中很重要的一环,Java平台提供了一个全新的集合框架.“集合框架”主要由一组用来操作对象的接口组成.不同接口描述一组不同数据类型.Java平台的完整集合框架如下图所示: 上 ...
- java基础---集合(1)
一. 基本概念 集合.数组都是对多个数据进行存储操作的结构,简称Java容器 数组:长度确定,类型确定,对于添加.删除.插入等操作效率不高,元素有序可重复 Java中集合框架顶层框架是:java.ut ...
- Java基础——集合源码解析 List List 接口
今天我们来学习集合的第一大体系 List. List 是一个接口,定义了一组元素是有序的.可重复的集合. List 继承自 Collection,较之 Collection,List 还添加了以下操作 ...
- Java基础—集合
一.概述 Java中的集合框架主要分为两大派别:Collection 和 Map —— 位于util包下 类的基础关系图如下(图片来自百度) 常用: List——有序可重复 Set——无序不可重复 M ...
- java基础集合简介Set(三)中
今天主要说夏set集合,每天抽出一个小时总结下,生活会更加美好! --< java.util >-- Set接口: 数据结构:数据的存储方式: Set接口中的方法和Collection中方 ...
- java基础集合经典训练题
第一题:要求产生10个随机的字符串,每一个字符串互相不重复,每一个字符串中组成的字符(a-zA-Z0-9)也不相同,每个字符串长度为10; 分析:*1.看到这个题目,或许你脑海中会想到很多方法,比如判 ...
- 十七、Java基础---------集合框架之Map
前两篇文章中介绍了Collection框架,今天来介绍一下Map集合,并用综合事例来演示. Map<K,V> Map<K,V>:Map存储的是键值对形式的元素,它的每一个元素, ...
- 十六、Java基础---------集合框架之Set
写在前面的话,这篇文章在昨天就写好了,今天打开的时候一不小心将第二天的文章粘贴到了这篇文章,很不幸的是除了标题之外依然面目全非,今天带着沉痛的心情再来写这篇文章! 上篇文章介绍了Collection体 ...
随机推荐
- WebView中的页面调试方法
在 iOS 12 中,苹果正式弃用 UIWebView,改成 WKWebView,参考官方声明. 后者在性能.稳定性.功能方面有很大提升,并且与 Safari 具有相同的 JavaScript 引擎( ...
- 一文带你深入理解K8s-Pod的意义和原理
本文分享自华为云社区<深入理解K8s-Pod的意义和原理>,作者:breakDawn. 在Kubernetes概念中,有以下五种概念: 容器container:镜像管理的最小单位 生产任务 ...
- Windows Server 2012 R2 无法更新问题
Windows Server 2012 R2 无法更新问题 新安装的ISO镜像由于年久失修,原先的Update服务器可能已经失效,需要安装更新补丁,才可以正常指向新的更新服务器,甚至连系统激活(输入正 ...
- JavaFx之播放MP4(二十七)
JavaFx之播放MP4(二十七) JavaFX 视频和音频支持,由 JavaFX 媒体类 Media.MediaPlayer.MediaView 和 AudioClip 提供. import jav ...
- C++ 学习宝藏网站分享
C++ 学习宝藏网站分享 1. C++ 在线参考手册 Cppreference https://zh.cppreference.com C++ 开发者必备的在线参考手册,是我最常访问的 C++ 网站之 ...
- html2pdf
nodejs 生成pdf比较靠谱,使用chrome核心渲染: puppeteer / phantom 爬虫都好用 good
- 8种ETL算法汇总大全!看完你就全明白了
摘要:ETL是将业务系统的数据经过抽取.清洗转换之后加载到数据仓库的过程,是构建数据仓库的重要一环,用户从数据源抽取出所需的数据,经过数据清洗,最终按照预先定义好的数据仓库模型,将数据加载到数据仓库中 ...
- EDS从小白到专家丨生态产业链高效协同的一计良策
本文分享自华为云社区<[EDS从小白到专家]第3期:生态产业链高效协同的一计良策>,作者:开天aPaaS小助手 . 号外! 华为将于2023年9月20-22日,在上海世博展览馆和上海世博中 ...
- 基于DMS的数仓智能运维服务,知多少?
摘要:GaussDB(DWS)使用DMS来承载数据库的智能运维体系,提供了数据库运维过程中的监控,分析,处理三大核心处理过程. 本文分享自华为云社区<GaussDB(DWS) 数据库智能监控运维 ...
- 拥抱时序数据库,构筑IoT时代下智慧康养数据存储底座
摘要:在HDZ城市行广州站中,来自华为云华为云数据库创新Lab向宇从时序数据库的技术角度,解读一下华为云时序数据库GaussDB(for Influx)如何应用在智慧健康养老行业. 本文分享自华为云社 ...