Java整理--数据结构篇

文章目录

数组

静态初始化

复制代码
    数据类型 数组名[]= new 数据类型[]{数据值,...};
    
    or
    
    数据类型[] 数组名= new 数据类型[]{数据值,...};
    
    or
    
    数据类型 数组名[]= {数据值,...};
    
    or
    
    数据类型[] 数组名= {数据值,...};

    int arr []=new int []{1,2,3};
    int arr1 []={1,2,3};
    int[]  arr2 ={1,2,3};
    int []  arr3 ={1,2,3};
    int []  arr4 =new int[]{1,2,3};

动态初始化

复制代码
    数据类型 数组名[]= new 数据类型[length];
    
    or
    
    数据类型[] 数组名= new 数据类型[length];

    int []  arr5 =new int[5];
    int [][] dp =new int[5][5];

声明方式

复制代码
// 方式1:声明时指定大小
int[] arr1 = new int[5];           // 默认初始化为0

// 方式2:声明并直接赋值
int[] arr2 = {1, 2, 3, 4, 5};

// 方式3:匿名数组
int[] arr3 = new int[]{1, 2, 3};

// 方式4:先声明后初始化
int[] arr4;
arr4 = new int[10];

多维数组

复制代码
// 二维数组
int[][] matrix = new int[3][4];     // 3行4列
int[][] matrix2 = {{1,2}, {3,4}};   // 直接初始化

// 不规则数组(每行长度不同)
int[][] jagged = new int[3][];
jagged[0] = new int[2];
jagged[1] = new int[5];
jagged[2] = new int[3];

数组核心特性

复制代码
长度固定	        创建后不可改变,length属性获取大小

索引访问	        从0开始,到length-1结束

连续内存	        元素在内存中连续存储

类型检查	        编译时检查类型安全

可存储对象		可存储基本类型或引用类型

遍历

复制代码
int[] nums = {10, 20, 30, 40, 50};

// 方式1:for循环(可修改元素)
for (int i = 0; i < nums.length; i++) {
System.out.println(nums[i]);
}

// 方式2:增强for循环(只读)
for (int num : nums) {
System.out.println(num);
}

// 方式3:Lambda表达式(Java 8+)
Arrays.stream(nums).forEach(System.out::println);

Arrays工具类

复制代码
    public static void main(String[] args) {
        int[] arr = {10,20,30,40,50,60,70,80,90,100};
//        Arrays.toString(arr);
        int[] arr1 = {10,20,30,40,50,60,70,30,90,100};
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.equals(arr1,arr));
        System.out.println(Arrays.binarySearch(arr,10));
        Arrays.sort(arr1);
        System.out.println(Arrays.toString(arr1));
    }
int[] nums = {3, 1, 4, 1, 5};
Arrays.sort(nums);  
// 结果:[1, 1, 3, 4, 5](升序,原地修改)
String[] strs = {"banana", "apple", "cherry"};
Arrays.sort(strs);  // 按自然顺序(Comparable)
Arrays.sort(nums, fromIndex, toIndex);  
// 排序 [fromIndex, toIndex)
// 示例:只排序第1到第4个元素(不含第4个)
Arrays.sort(nums, 1, 4);
//自定义比较器
Integer[] nums = {3, 1, 4, 1, 5};
// 降序排序
Arrays.sort(nums, (a, b) -> b - a);
// 或
Arrays.sort(nums, Collections.reverseOrder());

排序

复制代码
Arrays.sort(arr);                    // 快速排序,O(n log n)

查找

(必须先排序)

复制代码
int index = Arrays.binarySearch(arr, 4);  // 返回索引,不存在返回负数

填充

复制代码
Arrays.fill(arr, 0);                 // 全部填充为0

复制

复制代码
int[] copy = Arrays.copyOf(arr, 10);      // 复制并扩容
int[] range = Arrays.copyOfRange(arr, 1, 3); // 复制[1,3)范围

比较

复制代码
boolean equal = Arrays.equals(arr1, arr2);

转字符串

复制代码
String str = Arrays.toString(arr);   // [1, 3, 4, 5, 9]

多维数组转字符串

复制代码
int[][] matrix = {{1,2}, {3,4}};
String deep = Arrays.deepToString(matrix); // [[1, 2], [3, 4]]

并行排序

(大数据量更快)

数组与集合转换

复制代码
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;

数组 → List

(固定大小,不能增删)

复制代码
List<String> list = Arrays.asList("a", "b", "c");

数组 → ArrayList

(可变)

复制代码
List<String> arrayList = new ArrayList<>(Arrays.asList("a", "b"));

List → 数组

复制代码
String[] arr = list.toArray(new String[0]); 

基本类型数组 → List

(需要手动装箱)

复制代码
int[] nums = {1, 2, 3};
List<Integer> numList = Arrays.stream(nums).boxed().toList();
    Arrays.parallelSort(arr);

重点说明

获取数组长度

一维数组获取数组长度
复制代码
    数组名.length 
多维数组获取数组长度
复制代码
        int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6, 7},  // 可以不等长
    {8, 9}
};

// 获取行数(外层数组的长度)
int rows = matrix.length;        // 3

// 获取特定行的列数(内层数组的长度)
int colsRow0 = matrix[0].length; // 3

字符串String

java.lang.String

字符串不可变

直接赋值、new

复制代码
package com.yeyu.day1;
public class StringTest {
public static void main(String[] args) {
    String str1 = "hello";
    String str2 = "hello";
    str1="sss";
    System.out.println(str1);//sss
    String str3 = new String("sss1");
    System.out.println(str3);
    String str4 = new String();
    System.out.println(str4);//
    char[] chs={'a','b','c'};
    String str5 = new String(chs);
    System.out.println(str5);//abs
    byte[] bytes ={97,98};
    String str6 = new String(bytes);
    System.out.println(str6);//ab
    boolean result1=str1.equals(str2);
    System.out.println(result1);//false
    System.out.println(str2.charAt(1));//e
    System.out.println(str2.length());5
}
}

比较

boolean equals 完全一样

boolean equalsIgnoreCase 忽略大小写

遍历

public char charAt(int index)

public int length()

StringBuilder

可以看作一个容器,创建之后里面的内容是可变的

常用方法

append添加数据

reverse反转

length已经有多少

toString

capacity可以存多少字符

复制代码
package com.yeyu.day1;
public class StringBuilderTest {
public static void main(String[] args) {
    StringBuilder s=new StringBuilder();
    StringBuilder s1=new StringBuilder("abc");
    System.out.println(s1);//abc
    System.out.println(s1.reverse());//cba
    System.out.println(s1);//cba
    s1.append("abc");
    System.out.println(s1);//cbaabc
    System.out.println(s1.append(1));//cbaabc1
    System.out.println(s1.length());//7
    String ss=s1.toString();
    System.out.println(ss);//cbaabc1

}
}

StringJoiner

可以看着一个容器

public StringJoiner(间隔符号)

public StringJoiner(间隔符号,开始符号,结束符号)

复制代码
package com.yeyu.day1;
import java.util.StringJoiner;
public class StringJoinerTest {
public static void main(String[] args) {
    StringJoiner sj = new StringJoiner(",","{","}");
    sj.add("hello").add("world");
    System.out.println(sj);//{hello,world}
    System.out.println(sj.toString());//{hello,world}
    System.out.println(sj.length());//13
}
}

集合

单列集合

一次添加一个元素,均实现Collection接口

ArrayList、LinkedList

List接口

存取有序

有索引

可以存储重复的

TreeSet、HashSet、LinkedHashSet

Set接口

存取无序

无索引

不可以存储重复的

Collection接口

boolean add、remove、contains、isEmpty

void clear

int size

List接口

add remove set get

迭代器遍历

普通/增强for

foreach

ListIterator

倒序遍历:previous,hasPrevious

ArrayList

基于数组

长度可变,自动扩容

不能存基本数据类型

创建默认长度0

用了add之后默认10

超过了则扩容1.5倍

复制代码
package com.yeyu.day1;
import java.util.ArrayList;
public class ArrayListTest {
public static void main(String[] args) {
    ArrayList<String> list = new ArrayList<String>();
    list.add("hello");
    list.add("world");
    System.out.println(list);//[hello, world]
    ArrayList<String> list1 = new ArrayList<>();
    list1.add("hello");
    list1.add("world");
    System.out.println(list1);//[hello, world]
    System.out.println(list1.size());//2
    System.out.println(list1.contains("hello"));//true
    System.out.println(list1.equals(list));//true
    System.out.println(list.remove("hello"));//true
    System.out.println(list);//[world]
    System.out.println(list1);//[hello, world]
    System.out.println(list1.set(0,"world"));//hello
    System.out.println(list1);//[world, world]
}
}

LinkedList

基于双链表

List接口

存取有序

有索引

可以存储重复的

Set接口

存取无序

无索引

不可以存储重复的

TreeSet

基于红黑树结构

Set接口

存取无序

无索引

不可以存储重复的

红黑树

添加时当作红的

根节点是黑的

加入时

1、父红,叔红,

则父黑,叔黑,爷红

爷为当前节点再判断

2、父红,黑叔,当前节点为父右

则父为当前节点并左旋,再判断

3、父红,黑叔,当前节点为父左

父黑,爷红,爷右旋

平衡二叉树

左左,右旋

左右,左右旋

右右,左旋

右左,右左旋

自然排序
复制代码
public class TreeSetTest {
        public static void main(String[] args) {
            TreeSet<Student> treeSet = new TreeSet<>();
            //自然排序
            //使用add,会自动调用compareTo方法
            //小的左边,大的右边,一样的不存
            treeSet.add(new Student("张二",26));
            treeSet.add(new Student("李三",23));
            treeSet.add(new Student("王四",24));
            treeSet.add(new Student("毛五",25));
            System.out.println(treeSet);
            //取数据,左中右
            
        }
    }

public class Student implements Comparable<Student>{
@Override
public int compareTo(Student o) {
    return 1;
    //return this.age-o.age;//按年龄排
    // 1:正序排列,添加顺序
    //0:只有第一个
    //-1:倒序排列
}
/*
不重写toString会返回地址值
 */
@Override
public String toString() {
    return "Student{name='" + name + "', age=" + age + "}";
}

private String name;
private int age;
}
比较器排序
复制代码
//比较器排序
            TreeSet<Student> treeSet1 = new TreeSet<>(new Comparator<Student>() {
                @Override
                public int compare(Student o1, Student o2) {
                    return o1.getAge()-o2.getAge();
                }
            });

HashSet

Set接口

存取无序

无索引

不可以存储重复的

底层是哈希表结构

jdk8之前:数组+链表,jdk7头插法,jdk8尾插法

jdk8之后:数组+链表+红黑树,底层基于HashMap

索引计算:hashCode->原始哈希值->右移16位->哈希扰动->与原始哈希值异或进行二次哈希操作->数组长度减1再与之前结果与

提高查询性能
扩容数组

A、数组达到了有16*0.75(加载因子)

每次扩容原数组两倍大小

B、链表挂载超过8(阈值)个,并且数组长度没有超过64

链表转红黑树

链表挂载超过8(阈值)个,并且数组长度超过64

String类型
复制代码
    HashSet<String> hs = new HashSet<String>();
    hs.add("a");
    hs.add("c");
    hs.add("b");
    hs.add("b");
    System.out.println(hs.size());//3
    System.out.println(hs);//[a, b, c]
自定义对象类型
复制代码
@Override
public boolean equals(Object obj) {
    System.out.println("equals方法执行");
    if (this == obj) {
        return true;
    }
    if (obj == null || getClass() != obj.getClass()) {
        return false;
    }
    Student student = (Student) obj;
    return age==student.age&& Objects.equals(name,student.name);
    //return super.equals(obj);
}
@Override
public int hashCode() {
    System.out.println("hashCode方法执行");
    return 1;//去查
}
不重写equals方法
复制代码
        public static void main(String[] args) {
    HashSet<Student> hashSet = new HashSet<>();
    hashSet.add(new Student("张三",26));
    hashSet.add(new Student("张二",25));
    hashSet.add(new Student("张二",25));
    hashSet.add(new Student("李四",25));
    System.out.println(hashSet);//[Student{name=张三',age=26}, Student{name=张二',age=25}, Student{name=张二',age=25}, Student{name=李四',age=25}]
}
只重写equals方法
复制代码
HashSet<Student> hashSet = new HashSet<>();
        hashSet.add(new Student("张三",26));
        hashSet.add(new Student("张二",25));
        hashSet.add(new Student("张二",25));
        hashSet.add(new Student("李四",25));
        System.out.println(hashSet);//[Student{name=张三',age=26}, Student{name=张二',age=25}, Student{name=张二',age=25}, Student{name=李四',age=25}]
只重写hashCode方法

hashCode方法计算索引位置

return 1 未去重

重写equals方法和hashCode方法 return 1 去重
复制代码
        HashSet<Student> hashSet = new HashSet<>();
        hashSet.add(new Student("张三",26));
        hashSet.add(new Student("张二",25));
        hashSet.add(new Student("张二",25));
        hashSet.add(new Student("李四",25));
        //重写equals方法和hashCode方法,return 1
//        hashCode方法执行
//        hashCode方法执行
//        equals方法执行
//        hashCode方法执行
//        equals方法执行
//        equals方法执行
//        hashCode方法执行
//        equals方法执行
//        equals方法执行
//                [Student{name=张三',age=26}, Student{name=张二',age=25}, Student{name=李四',age=25}]
        System.out.println(hashSet);//[Student{name=张三',age=26}, Student{name=张二',age=25}, Student{name=李四',age=25}]

LinkedHashSet

基于哈希表

每个元素额外增加一个双链表机制记录存储顺序

Set接口

存取有序

无索引

不可以存储重复的

复制代码
    LinkedHashSet<String> linkedHashSet = new LinkedHashSet<>();
    linkedHashSet.add("ss");
    linkedHashSet.add("sss");
    linkedHashSet.add("sss");
    System.out.println(linkedHashSet);

Collections集合工具类

可变参数

本质是数组

格式:

数据类型... nums

or

其他参数, 数据类型... nums

Collections类常用方法

复制代码
public static <T> boolean addAll(Collection<? super T> c,T... elements)批量添加
public static shuffle(List<?> list)打乱
public static binarySearch(List<T> list,T key)二分法查找元素
public static max(Collection<T> c)默认自然排序的最值
public static min
public static swap(List<?> list,int i,int j)交换元素
自定义对象获取最值需要重写Comparable接口

    ArrayList<String> students = new ArrayList<>();
    Collections.addAll(students,"a","n","c","b");//[a, n, c, b]
    System.out.println(students);
    System.out.println(Collections.binarySearch(students,"b"));//-2
    Collections.sort(students);
    System.out.println(students);//[a, b, c, n]
    System.out.println(Collections.binarySearch(students,"b"));//1
    Collections.shuffle(students);
    System.out.println(students);//[n, c, a, b]
    ArrayList<Integer> students1 = new ArrayList<>();
    Collections.addAll(students1,1,2,3,4,5);
    System.out.println(Collections.max(students1));//5
    System.out.println(Collections.min(students1));//1
            Collections.sort(students1,Collections.reverseOrder());
    System.out.println(students1);//[5, 4, 3, 2, 1]
    ArrayList<Integer> students2 = new ArrayList<>();
    Collections.addAll(students2,1,2,3,4,5);
    Collections.sort(students2,new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o2-o1;
        }
    });
    System.out.println(students2);//[5, 4, 3, 2, 1]

双列集合

一次添加两个元素

均有Map接口

Map接口

key不允许重复

value可以重复

Entry表示键值对

关键方法
复制代码
    Map<String,String> map = new HashMap<>();
    //添加
    map.put("a","b");//返回的是被覆盖的值
    map.put("c","d");//返回null
    map.put("b","f");
    map.put("c","h");//返回d
    //HashMap存取顺序不一致
    System.out.println(map);//{a=b, b=f, c=h}
    //删除
    //删除键对应的键值对,返回键对应的值
    map.remove("c");
    System.out.println(map);//{a=b, b=f}
    System.out.println(map.isEmpty());//false
    System.out.println(map.size());//2
    System.out.println(map.containsKey("a"));//true
    System.out.println(map.containsValue("f"));//true
    map.clear();
    System.out.println(map);//{}
    System.out.println(map.isEmpty());//true
三种遍历
键集合
复制代码
    //获取所有键
    Set<String> keys = map.keySet();
    System.out.println(keys);//[a, b, c]
    //遍历键集合,遍历值
    for(String key:keys){
        System.out.println(map.get(key));//b f h
    }
Entry键值对集合
复制代码
    Set<Map.Entry<String,String>> entryset= map.entrySet();
    for (Map.Entry<String,String> entry:entryset){
        System.out.println(entry.getKey()+":"+entry.getValue());
//            a:b
//            b:f
//            c:h
forEach
复制代码
    map.forEach(new BiConsumer<String, String>() {
        @Override
        public void accept(String key, String value) {
            System.out.println(key+":"+value);
        }
    });
    map.forEach((k,v)->{
        System.out.println(k+":"+v);
    });    

TreeMap

键排序,自定义对象需要实现Comparable接口

红黑树

复制代码
    TreeMap<Person,String> treemap = new TreeMap<>();

HashMap

键唯一,需重写hashCode和equals方法

哈希表

键->哈希值

jdk8开始,链长度超过8且数组长度>=64,自动转为红黑树

复制代码
HashMap<Person,String> hashmap = new HashMap<>();

LinkedHashMap

键唯一,且保证存取顺序

哈希表+双向链表

复制代码
LinkedHashMap<Person,String> linkedhashmap = new LinkedHashMap<>();

迭代器遍历

复制代码
public Iterator<E> iterator()
Iterator<E> name=对象.iterator()
boolean hasNext()
E next()将元素取出,并向后移动下一个
void remove一出迭代器返回的最后一个元素

泛型

jdk5引入

泛型类

泛型方法

复制代码
package com.yeyu.day3;

public class NiMingNeiBuLeiTest {
    public static void main(String[] args) {
        // 方法的形参是接口类型,传入接口的实现类对象
//        test(new InterImpl());


//        test(new Inter() {
//            @Override
//            public void show() {
//                System.out.println("匿名内部类");//匿名内部类
//            }
//        });
//        new 类名(){}:继承这个类
//        new 接口名(){}:实现这个接口

        test((msg)->{System.out.println(msg);});//Lambda
        //():匿名内部类被重新写方法的形参列表
        //形参参数类型可以不写
        //若只有一个形参,类型和()可以不写
        //方法体只有一行{}和;可以不写
        //只有一行return,return和;必须省略
    }
    public static void test(Inter i){
        i.show("形参");
    }
}

泛型接口

复制代码
interface Inter1<E>{
//    void show();
    void show(E msg);
}
class  Inter2 implements Inter1<String>{
    @Override
    public void show(String msg) {}
}
class  Inter3<E> implements Inter1<E>{
    @Override
    public void show(E msg) {}
}

泛型通配符

?:任意类型

? extends E:可以传入E或者E的子类

? super E:可以传入E或者E的父类

Queue

复制代码
// 插入元素
boolean add(E e)      // 队列满时抛出异常
boolean offer(E e)    // 队列满时返回false(推荐)

// 移除并返回队首
E remove()            // 空队列时抛出异常
E poll()              // 空队列时返回null(推荐)

// 仅查看队首(不移除)
E element()           // 空队列时抛出异常
E peek()              // 空队列时返回null(推荐)

Queue 接口

复制代码
// 基础接口,定义队列的基本操作
public interface Queue<E> extends Collection<E>

主要实现类

复制代码
实现类	                特点	                线程安全	适用场景

LinkedList	        	双向链表实现	        	❌ 否	普通队列操作

ArrayDeque	        	数组实现的双端队列		❌ 否	高性能双端队列,优先于Stack

PriorityQueue	        优先级堆实现      		❌ 否	需要按优先级排序的场景

ConcurrentLinkedQueue	无锁并发队列	        	✅ 是	高并发单生产者-单消费者

LinkedBlockingQueue		可选有界阻塞队列	        ✅ 是	生产者-消费者模式

ArrayBlockingQueue		有界阻塞队列	        	✅ 是	固定容量缓冲

SynchronousQueue		不存储元素	       	 	✅ 是	直接传递

DelayQueue	        	延迟获取元素	        	✅ 是	延迟任务调度

基础队列-LinkedList实现

复制代码
import java.util.LinkedList;
import java.util.Queue;

public class QueueDemo {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();

入队

复制代码
        queue.offer("任务1");
        queue.offer("任务2");
        queue.offer("任务3");

出队

复制代码
        while (!queue.isEmpty()) {
            System.out.println("处理: " + queue.poll());
        }
    }
}

双端队列

复制代码
import java.util.ArrayDeque;
import java.util.Deque;

public class DequeDemo {
public static void main(String[] args) {
Deque<Integer> deque = new ArrayDeque<>();

两端操作

复制代码
        deque.addFirst(1);  // 队首添加
        deque.addLast(2);   // 队尾添加
        deque.removeFirst(); // 移除队首
        deque.removeLast();  // 移除队尾
    }
}
相关推荐
晚枫歌F2 小时前
btree B树实现key-value存储
开发语言·数据结构
wangchen_02 小时前
B树、B+树详解
数据结构·b树·哈希算法
foundbug9992 小时前
多智能体三维编队飞行控制MATLAB实现
开发语言·matlab
炸膛坦客2 小时前
单片机/C语言八股:(七)C 程序运行时内存布局的动态变化
c语言·开发语言
吴声子夜歌2 小时前
小程序——界面API(一)
java·javascript·小程序
予枫的编程笔记2 小时前
【面试专栏|Java并发编程】从Runnable到Callable,Java4种线程创建方式
java·多线程·thread·java面试·runnable·callable·java线程
无尽的罚坐人生2 小时前
hot 100 101. 对称二叉树
数据结构·算法·leetcode
野犬寒鸦2 小时前
SAP后端实习开发面试:操作系统与网络核心考点及Linux与Redis
java·服务器·网络·后端·面试
ServBay2 小时前
代码减半,10分钟彻底告别 Java 开发旧习
java·后端