计算机核心基础之数据结构
-
什么是数据结构
- 是计算机科学中一个非常重要的概念,它指的是相互之间存在一种或多种特定关系的数据元素的集合。
- 简单来说,数据结构就是组织、存储和操作数据的方式或方法。
- 在计算机程序中,合理的数据结构能够大大提高程序的运行效率,减少存储空间的使用,并使程序更易于理解和维护
-
用途场景
- 提高程序效率:通过选择合适的数据结构,可以优化程序的性能,减少不必要的计算和存储开销。
- 简化算法设计:数据结构为算法的实现提供了基础,通过抽象数据之间的关系,可以使算法更加清晰和易于理解。
-
数据结构分类
-
线性数据结构
- 数组(Array):固定大小、连续存储的数据元素集合。
- 链表(LinkedList):由节点组成,每个节点包含数据元素和指向下一个节点的指针。
- 栈(Stack):后进先出(LIFO)的数据结构,只允许在一端进行插入和删除操作。
- 队列(Queue):先进先出(FIFO)的数据结构,在一端插入元素,在另一端删除元素。
-
非线性数据结构
- 树(Tree):由节点和边组成的层次结构,每个节点可以有零个或多个子节点。
- 图(Graph):由节点(或顶点)和边(或弧)组成的集合,用于表示复杂的数据关系。
-
Java进阶核心之Collection集合框架概要
-
什么是Java的集合框架
- Java的集合框架(Collection Framework)是一个用于表示和操作对象的集合的统一架构。
- 它包含了许多接口、实现类以及算法,可以高效地存储和操作多个对象。
- 集合框架是Java API的一部分,它允许我们将对象组合成更大的结构,同时提供了对这些结构的高层次操作。
- 通俗来说:就是java已经封装好的数据结构类,我们开发可以直接用
-
集合框架的主要接口和类
- Collection接口
- 是所有集合类的根接口,定义了集合类应该具备的一些基本方法,如添加、删除、遍历等。
- 常见方法列表
boolean add(E e) 向集合中添加指定的元素。如果集合已经包含该元素,则此方法可能不执行任何操作(对于Set而言)。 boolean addAll(Collection<? extends E> c) 将指定集合中的所有元素添加到此集合中(可选操作)。 void clear() 移除集合中的所有元素(可选操作)。 boolean contains(Object o) 如果此集合包含指定的元素,则返回true。 boolean containsAll(Collection<?> c)如果此集合包含指定集合中的所有元素,则返回true boolean isEmpty() 如果此集合不包含任何元素,则返回true。 Iterator<E> iterator()返回在此集合中的元素上进行迭代的迭代器。 boolean remove(Object o)从此集合中移除指定的元素(如果存在)。 boolean removeAll(Collection<?> c)从此集合中移除指定集合中包含的所有元素(可选操作)。 boolean retainAll(Collection<?> c)仅保留此集合中也包含在指定集合中的元素(可选操作)。 int size()返回此集合中的元素数(其容量)。
- List接口
- 继承了Collection接口,代表一个有序集合,允许有重复的元素。
- 实现类有ArrayList、LinkedList、Vector等。
- Set接口
- 继承了Collection接口,代表一个无序集合,不允许有重复的元素。
- 实现类有HashSet、TreeSet等。
- Queue接口
- 代表一个队列,用于保存等待处理的元素,队列是一种特殊的线性表
- 它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。
- 实现类有LinkedList(它同时实现了List和Queue接口)、PriorityQueue等。
- Map接口(没继承Collection接口,本身是顶级接口)
- 代表一个映射关系,将键(Key)映射到值(Value),键不允许重复,但值可以重复。
- 实现类有HashMap、TreeMap、Hashtable等。
- Collection接口
-
迭代器
- 集合框架中的一个重要概念,它提供了一种遍历集合元素的方式,而不需要了解集合底层的实现细节。
- 使用迭代器可以安全地遍历集合,并且可以在遍历过程中安全地修改集合(除了并发修改外)。
-
例:
import java.util.ArrayList; import java.util.List; public class CollectionDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); for (String str : list) { System.out.println(str); } list.remove("c"); for (String str : list) { System.out.println(str); } } } -
总结
- Java的集合框架为我们提供了一种统一的方式来操作对象集合,它包括了多种类型的集合(如List、Set、Queue、Map等)
- 以及许多用于操作这些集合的算法和工具类,掌握集合框架是Java编程中非常重要的一部分。
Java进阶核心之集合框架List
-
什么是List数据结构
- 在Java的集合框架中,
List接口是一个有序的集合,允许元素有重复。 List接口继承了Collection接口,提供了许多额外的功能,比如基于索引的插入、删除和访问元素等。- 常见的
List接口的实现类有ArrayList、LinkedList和Vector。
- 在Java的集合框架中,
-
List接口的实现类
- ArrayList
- 底层基于数组实现,查询效率高,增删效率低(因为需要移动元素)。
- 线程不安全,但性能较高。
- 适用于需要频繁查询的场景。
- LinkedList
- 底层基于双向链表实现,查询效率低(需要从头或尾遍历),增删效率高。
- 提供了额外的头尾操作方法,如
addFirst(),addLast(),getFirst(),getLast(),removeFirst(),removeLast()等。 - 线程不安全。
- 适用于需要频繁增删的场景,尤其是首尾操作。
- ArrayList
-
List接口的主要方法
void add(int index, E element): 在指定位置插入元素。E get(int index): 返回指定位置的元素。int indexOf(Object o): 返回此列表中指定元素的首次出现的索引,如果此列表不包含该元素,则返回-1。int lastIndexOf(Object o): 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含该元素,则返回-1。E remove(int index): 移除指定位置的元素。boolean contains(Object o): 如果此列表包含指定的元素,则返回true。Iterator<E> iterator(): 返回在此列表中的元素上进行迭代的迭代器
-
例:
import java.util.ArrayList; import java.util.List; public class ListDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); System.out.println(list.get(1)); list.add("d"); for (String fruit : list) { System.out.println(fruit); } list.remove(2); for (String str : list) { System.out.println(str); } } } -
使用注意事项
- 使用
List集合时,要注意索引越界的问题,即不要访问或操作不存在的索引位置。 - 在多线程环境下,如果需要对
List进行并发操作,需要考虑线程安全的问题,可以选择使用线程安全的实现类。 - 根据实际需求选择合适的
List实现类,获得更好的性能
- 使用
Java进阶核心之哈希表和Map
-
什么是散列表(Hash table,也叫哈希表)
- 是根据关键码值(Key value)而直接进行访问的数据结构。
- 它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度 。
- 这个映射函数叫做散列函数,存放记录的数组叫做散列表。
- 给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址
- 则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数
- 散列函数 能使对一个数据序列的访问过程更加迅速有效,通过散列函数,数据元素将被更快地定位
-
什么是Map
- 在Java的集合框架中,
Map接口是一种存储键值对(key-value pair)的数据结构。 Map不允许出现重复的键(key),但允许多个键映射到相同的值(value)。Map接口并不继承自Collection接口,而是与Collection接口并行存在,用于处理键值对映射数据。- 常见的
Map接口实现类有HashMap、LinkedHashMap、TreeMap等。
- 在Java的集合框架中,
-
Map接口的实现类
- HashMap
- 基于哈希表实现,允许null键和null值。
- 不保证映射的顺序,特别是它不保证该顺序恒久不变。
- 性能通常优于
Hashtable和TreeMap。
- LinkedHashMap
- 类似于
HashMap,但遍历顺序是按照键值对插入到映射中的顺序(插入顺序)或最近最少使用(LRU)顺序。 - 提供了按访问顺序(访问顺序)或插入顺序(插入顺序)遍历映射的方法。
- 类似于
- TreeMap
- 基于红黑树实现,能够按照键的自然顺序或自定义顺序进行排序。
- 所有的元素都根据键的自然顺序(或创建
TreeMap时提供的Comparator进行排序)。 - 适用于需要有序遍历的场景。
- HashMap
-
Map接口的主要方法
V put(K key, V value): 将指定的值与此映射中的指定键关联(可选操作)。如果包含一个该键的映射关系,则旧值被替换。V get(Object key): 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回null。V remove(Object key): 如果存在一个键的映射关系,则从此映射中移除它(可选操作)。boolean containsKey(Object key): 如果此映射包含指定键的映射关系,则返回true。boolean containsValue(Object value): 如果此映射将一个或多个键映射到指定值,则返回true。int size(): 返回此映射中的键-值映射关系的数量。boolean isEmpty(): 如果此映射不包含键-值映射关系,则返回true。Set<K> keySet(): 返回此映射中包含的键的Set视图。Collection<V> values(): 返回此映射中包含的值的Collection视图。Set<Map.Entry<K,V>> entrySet(): 返回此映射中包含的映射关系的Set视图。
-
例:
import java.util.HashMap; import java.util.Map; public class MapDemo { public static void main(String[] args) { Map<String, Integer> map = new HashMap<>(); map.put("a", 1); map.put("b", 2); map.put("c", 3); System.out.println(map.get("a")); // 遍历键 for (String key : map.keySet()) { System.out.println(key); } // 遍历值 for (Integer value : map.values()) { System.out.println(value); } // 遍历键值对 for (Map.Entry<String, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + ":" + entry.getValue()); } map.remove("c"); for (Map.Entry<String, Integer> entry : map.entrySet()) { System.out.println(entry.getKey() + ":" + entry.getValue()); } } } -
注意事项
- 在使用
Map时,要注意键的唯一性,不要试图插入重复的键。 - 如果需要在多线程环境下使用
Map,需要考虑线程安全的问题。
- 在使用
第5集 Java进阶核心之集合框架Set
-
什么是Set
- 在Java的集合框架中,
Set接口是一个不包含重复元素的集合。 - 它继承自
Collection接口,包含了Collection接口的所有方法,如add(),remove(),contains(),size(),isEmpty()等 Set集合主要用于存储无序且不重复的元素,不保证集合中元素的顺序,某些Set实现类可能会对元素进行排序)
- 在Java的集合框架中,
-
Set接口的实现类
- HashSet
- 基于哈希表实现,不保证元素的迭代顺序,也不保证元素的顺序在长时间内保持不变。
- 性能通常优于其他
Set实现类,因为它提供了常数时间的添加、删除和查找操作。
- LinkedHashSet
- 类似于
HashSet,但迭代顺序是元素插入到集合中的顺序(插入顺序)。 - 在需要保持元素插入顺序的场景中很有用。
- 类似于
- TreeSet
- 基于红黑树实现,能够对元素进行自然排序或根据创建
TreeSet时提供的Comparator进行排序。 - 适用于需要有序集合的场景。
- 基于红黑树实现,能够对元素进行自然排序或根据创建
- HashSet
-
Set接口的主要方法
boolean add(E e): 如果此集合尚未包含指定元素,则添加指定元素。boolean addAll(Collection<? extends E> c): 如果指定集合中的所有元素都尚未添加到此集合中boolean contains(Object o): 如果此集合包含指定的元素,则返回true。boolean containsAll(Collection<?> c): 如果此集合包含指定集合中的所有元素,则返回true。boolean removeAll(Collection<?> c): 移除此集合中那些也包含在指定集合中的所有元素(可选操作)。boolean retainAll(Collection<?> c): 仅保留此集合中也包含在指定集合中的元素(可选操作)。
-
例:
import java.util.HashSet; import java.util.Set; public class SetDemo { public static void main(String[] args) { Set<String> set = new HashSet(); set.add("a"); set.add("b"); set.add("c"); for (String str : set) { System.out.println(str); } System.out.println(set.contains("a")); set.remove("c"); for (String str : set) { System.out.println(str); } } } -
注意事项
- 在使用
Set集合时,要注意集合中元素的唯一性,不要添加重复的元素。 - 如果需要在集合中保持元素的插入顺序或进行排序,请选择适当的
Set实现类(如LinkedHashSet或TreeSet)。 - 在多线程环境下使用
Set集合时,需要考虑线程安全的问题。 - 如果需要线程安全的
Set集合,可以使用Collections.synchronizedSet()方法
- 在使用
Java集合框架遍历之迭代器Iterator
-
需求
- 容器里面很多元素,如果需要遍历里面的元素,应该怎么操作?
- 使用循环遍历集合:普通for循环 和 增强for循环
-
迭代器 Iterator 概述
- Iterator是java中的一个接口,核心作用就是用来遍历容器的元素
- 当容器实现了Iterator接口后,可以通过调用Iterator()方法获取一个 Iterator对象
- 迭代器本身并不属于集合结构的一部分,而是用于遍历集合的工具。
- 为啥是调用容器里面的Iterator方法呢?
- 因为容器的实现有多种,不同的容器遍历规则不一样,比如ArrayList/LinkedList/HashSet/TreeSet等,
- 能够顺序地访问一个集合(Collection)的元素,而又不需要知道该集合的底层表示。
- 所以设计了Iterator接口,让容器本身去实现这个接口,实现里面的方法,
- 从而让开发人员不用关系容器的遍历机制,直接使用对应的方法即可
- 三个核心方法
- boolean hashNext() :用于判断iterator内是否有下个元素,如果有则返回true,没有则false
- Obejct next():返回iterator的下一个元素,同时指针也会向后移动1位
- void remove():删除指针的上一个元素(容易出问题,删除元素不建议使用容器自己的方法)
-
使用迭代器的步骤
- 获取迭代器对象
- 通过调用集合的
iterator()方法,我们可以获取到该集合的迭代器对象。 ElementType是集合中元素的类型,collection是需要遍历的集合对象。
- 通过调用集合的
- 判断迭代器中是否还有元素:
- 使用
iterator.hasNext()方法来判断迭代器中是否还有下一个元素
- 使用
- 访问集合中的元素:
- 使用
iterator.next()方法来获取迭代器中的下一个元素。 - 在调用
next()方法之前,必须确保迭代器中还有元素,否则会抛出NoSuchElementException异常
- 使用
- 安全地遍历集合:
- 在遍历集合的过程中,如果需要删除某个元素,应该使用迭代器的
remove()方法,而不是集合的remove()方法 - 直接使用集合的
remove()方法会导致在并发修改集合的情况下抛出ConcurrentModificationException异常。
- 在遍历集合的过程中,如果需要删除某个元素,应该使用迭代器的
- 获取迭代器对象
-
例:
import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class IteratorDemo { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String next = iterator.next(); System.out.println(next); if (next.equals("c")) { iterator.remove(); } } for (String str : list) { System.out.println(str); } } } -
注意事项
- 迭代器遍历集合时,只能单向遍历,无法从后往前遍历。
- 如果在遍历过程中需要修改集合(如删除元素),应该使用迭代器的
remove()方法,而不是集合的remove()方法。 - 不同循环找元素方式选择,最终看使用场景,性能会有轻微差别,但是可以忽略