Java高级内容复习笔记

目录

集合框架

集合框架概览

泛型

List接口

ArrayList类

LinkedList类

集合遍历

一个一个手动获取

使用for循环遍历

使用迭代器遍历(需要学习)

使用for-each遍历(简单推荐)

Set接口

HashSet类

TreeSet类

Map接口

Map常用操作方法

HashMap

TreeMap

LinkedHashMap

Queue队列

Deque队列

Stack栈

Collections工具类

多线程

主要内容略过

辅助/补充内容

多线程各类状态通俗理解


集合框架

简单理解,就是包含了算法与数据结构课程中的一些数据结构,可以直接调用,不需要手动构造这些数据结构

使用集合框架需要import对应的包

  • java.util.ArrayList
  • java.util.LinkedList
  • java.util.HashMap
  • java.util.HashSet
  • java.util.Hashtable
  • java.util.Vector

集合框架概览

Collection接口:泛指广义上集合,主要表示List和Set两种存储方式。

List接口:表示列表,规定了允许记录添加顺序,允许元素重复规范。元素有序且可重复,可以按照数组理解。

Set接口:表示狭义上集合,规定了不记录添加顺序,不允许元素重复规范。元素无序且唯一,可以按照哈希表理解。

Map接口:表示映射关系,规定了两个集合映射关系规范。每个元素对应一个键值,可以按照Python字典结构理解。

注意:都是接口,定义的是一些规范,是靠例如ArrayList等来具体实现的。

泛型

泛型可以理解为未知数据类型标志,当一个数据、返回值等数据类型不确定、可以是多种数据类型时,在编写类代码时,可以指定一个字母作为泛型代表未知数据类型,在创建对象、调用方法时再指定具体数据类型。
以下代码创建了一个数据类型不定的类与返回值不确定的方法:

public class MyArrayList<E> {  
    E e;  
    public E method(E e) {  
        return e;  
    }  
}

当创建这个类的实例时,可以指定具体数据类型:

MyArrayList<String> stringMyArrayList = new MyArrayList<>();

List接口

表示列表,规定了允许记录添加顺序,允许元素重复规范。元素有序且可重复,可以按照数组理解。

该接口常用的实现类有:

ArrayList类:数组列表,表示数组结构,底层采用数组实现,使用最多,重点。

LinkedList类:链表,表示双向列表和双向队列结构,采用链表实现,使用不多。

Stack类:栈,表示栈结构,采用数组实现,使用不多。

Vector类:向量,其实就是古老的ArrayList,采用数组实现,使用不多。

ArrayList类

ArrayList常用方法:
public class ArrayListDemo1 {
	public static void main(String[] args) {
		// 创建一个默认长度的列表对象
		List list = new ArrayList();
		// 打印集合中元素的个数
		System.out.println("元素数量:"+list.size());//0
		// 添加操作:向列表中添加4个元素
		list.add("Will");
		list.add(100);
		list.add(true);
		list.add("Lucy");
		// 查询操作:
		System.out.println("列表中所有元素:"+list);//输出:[Will, 100, true, Lucy]
		System.out.println("元素数量:"+list.size());//4
		System.out.println("第一个元素:"+list.get(0));//Will
		
		// 修改操作:把索引为2的元素,替换为wolfcode
		list.set(2, "wolfcode");
		System.out.println("修改后:"+list);//输出:[Will, 100, wolfcode, Lucy]
		
		// 删除操作:删除索引为1的元素
		list.remove(1);
		System.out.println("删除后:"+list);//输出:[Will, wolfcode, Lucy]
	}
}

LinkedList类

LinkedList类,底层采用链表算法,实现了链表,队列,栈的数据结构。无论是链表还是队列主要操作的都是头和尾的元素,因此在LinkedList类中除了List接口的方法,还有很多操作头尾的方法。

方法:

boolean offerFirst(Object e) 在此列表的开头插入指定的元素。

boolean offerLast(Object e) 在此列表末尾插入指定的元素。

Object peekFirst() 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。

Object peekLast() 获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。

Object pollFirst() 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。

Object pollLast() 获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。

void push(Object e) 将元素推入此列表所表示的栈。

Object pop() 从此列表所表示的栈处弹出一个元素。

Object peek() 获取但不移除此列表的头(第一个元素)。
 

public class LinkedListDemo {
	public static void main(String[] args) {
		LinkedList list = new LinkedList();
		//添加元素
		list.addFirst("A");
		list.addFirst("B");
		System.out.println(list);//[B, A]
		list.addFirst("C");
		System.out.println(list);//[C, B, A]
		list.addLast("D");
		System.out.println(list);//[C, B, A, D]
		//获取元素
		System.out.println("获取第一个元素:" + list.getFirst());//C
		System.out.println("获取最后一个元素:" + list.getLast());//D
		//删除元素
		list.removeFirst();
		System.out.println("删除第一个元素后:" + list);//[B, A, D]
		list.removeLast();
		System.out.println("删除最后一个元素后:" + list);//[B, A]
	}
}

集合遍历

一个一个手动获取

List<String> list = new ArrayList<>();
//以手动添加为例 获取同理
list.add("西施");
list.add("王昭君");
list.add("貂蝉");
list.add("杨玉环");

使用for循环遍历

for (int index = 0; index < list.size(); index++) {
	String ele = list.get(index);
	System.out.println(ele);
}

使用迭代器遍历(需要学习)

Iterator表示迭代器对象,迭代器中拥有一个指针,默认指向第一个元素之前

·boolean hasNext():判断指针后是否存在下一个元素

·Object next():获取指针位置下一个元素,获取后指针向后移动一位

·void remove():从迭代器指向的集合中移除迭代器返回的最后一个元素

Iterator<String> it = list.iterator();
//首先创建迭代器对象 map方法与此不同
while(it.hasNext()) {
	String ele = it.next();
	System.out.println(ele);
}

使用for-each遍历(简单推荐)

底层仍是Iterator实现

for (String ele : list) {
	System.out.println(ele);
}

Set接口

表示狭义上集合,规定了不记录添加顺序,不允许元素重复规范。元素无序且唯一,可以按照哈希表理解。

Set只包含从Collection继承的方法,不过Set无法记住添加的顺序,不允许包含重复的元素。当试图添加两个相同元素进Set集合,添加操作失败,add()方法返回false。

Set接口常用的实现类有:

  • HashSet类:底层采用哈希表实现,使用最多,重点。
  • TreeSet类:底层采用红黑树实现,可以对集合中元素排序,使用不多。

HashSet和TreeSet操作方法一样如下:

HashSet类

HashSet 是Set接口的实现类,底层数据结构是哈希表,集合容器不记录元素的添加顺序,也不允许元素重复。通常我们也说HashSet中的元素是无序的、唯一的

public class HashSetDemo {
	public static void main(String[] args) {
		Set<String> set = new HashSet<>();
		//添加操作:向列表中添加4个元素
		set.add("Will");
		set.add("wolf");
		set.add("code");
		set.add("Lucy");
        
		//查询操作:
		System.out.println("集合中所有元素:" + set);//[code, wolf, Will, Lucy]
		System.out.println("元素数量:" + set.size());//4
		System.out.println("是否存在某个元素:" + set.contains("code"));//true
		System.out.println("是否存在某个元素:" + set.contains("code2"));//false
        
		//删除操作:删除code元素
		set.remove("code");
		System.out.println("删除后:" + set);//[wolf, Will, Lucy]
		
        //使用for-each遍历
		for (String ele : set) {
			System.out.println(ele);
		}
        
		//使用迭代器遍历
		Iterator<String> it = set.iterator();
		while (it.hasNext()) {
			Object ele = it.next();
			System.out.println(ele);
		}
	}
}

TreeSet类

TreeSet会对存入的元素默认进行从小到大排序,要保证TreeSet中存储的元素是相同的数据类型,否则会报错。

public class TreeSetDemo{
	public static void main(String[] args) {
		Set<String> set = new TreeSet<>();
		set.add("wolf");
		set.add("will");
		set.add("sfef");
		set.add("allen");
		System.out.println(set);// [allen, sfef, will, wolf]
        //自动按照字母大小顺序从a~z排序
	}
}

Map接口

Map可以按照Python字典的结构来理解,也可以按照函数的概念来理解,如图

从定义和结构图上,可以看出Map并不是集合,而表示两个集合之间的一种关系,故Map没有实现Collection接口

在Map中,要求A集合中的每一个元素都可以在B集合中找到唯一的一个值与之对应。这句话可以解读为一个A集合元素只能对应一个B集合元素,也就说A集合中的元素是不允许重复的,B集合中的元素可以重复,也可不重复。那么不难推断出A集合应该是一个Set集合B集合应该是List集合举例理解:A集合是身份证号,是唯一的。B集合是姓名,是可以重复的。

A集合中的元素称为key,B集合中的元素称为value。每一对key-value表示为Entry

因此,一个Map结构也可以理解为是Entry的集合,即Set。
一般的,我们依然习惯把Map称之为集合, 不过要区分下,Set和List是 单元素集合,Map是 双元素集合。
注意: Map接口并没有继承于Collection接口也没有继承于Iterable接口,所以不能直接对Map使用for-each操作遍历。

Map常用操作方法

以下标红的是重点方法。

添加操作

boolean put(Object key,Object value):存储一个键值对到Map中

boolean putAll(Map m):把m中的所有键值对添加到当前Map中

删除操作

Object remove(Object key):从Map中删除指定key的键值对,并返回被删除key对应的value
修改操作

修改操作无专门的方法,可以调用put方法,存储相同key,不同value的键值对,可以覆盖原来的。


查询操作

int size():返回当前Map中键值对个数

boolean isEmpty():判断当前Map中键值对个数是否为0.

Object get(Object key):返回Map中指定key对应的value值,如果不存在该key,返回null

boolean containsKey(Object key):判断Map中是否包含指定key

boolean containsValue(Object value):判断Map中是否包含指定value

Set keySet():返回Map中所有key所组成的Set集合

Collection values():返回Map中所有value所组成的Collection集合

Set entrySet():返回Map中所有键值对所组成的Set集合

HashMap

HashMap底层基于哈希表算法,Map中存储的key对象的hashCode值决定了在哈希表中的存储位置,因为Map中的key是Set,所以不能保证添加的先后顺序,也不允许重复。

HashMap key的底层数据结构是哈希表

补充:Hashtable 是一个古老的 Map 实现类,不建议使用

示例: 统计一个字符串中每个字符出现次数

public class HashMapDemo2{
	public static void main(String[] args) {
		String str = "ABCDEFABCDEABCDABCABA";
		//把字符串转换为char数组
		char[] charArray = str.toCharArray();
		//Map的key存储字符,value存储出现的次数
		Map<Character, Integer> map = new HashMap<>();
		//迭代每一个字符
		for (char ch : charArray) {
			//判断Map中是否已经存储该字符
			if (map.containsKey(ch)) {
				Integer count = map.get(ch);
				//如果已经存储该字符,则把出现次数加上1
				map.put(ch, count+1);
			}else {
				//如果没有存储该字符,则把设置次数为1
				map.put(ch, 1);
			}
		}
		System.out.println(map); 

	}
}

TreeMap

TreeMap key底层基于红黑树算法,因为Map中的key是Set,所以不能保证添加的先后顺序,也不允许重复,但是Map中存储的key会默认使用自然排序(从小到大),和TreeSet一样,除了可以使用自然排序也可以自定义排序。

需求:测试HashMap和TreeMap中key的顺序
 

public class App {
	public static void main(String[] args) {
		Map<String, String> map = new HashMap<>();
		map.put("girl4", "杨玉环");
		map.put("girl2", "王昭君");
		map.put("key1", "西施");
		map.put("key3", "貂蝉");
		System.out.println(map);
		//-------------------------------------------
		map = new TreeMap<>(map);
		System.out.println(map);
	}
}

运行结果:

{key1=西施, girl4=杨玉环, key3=貂蝉, girl2=王昭君}
{girl2=王昭君, girl4=杨玉环, key1=西施, key3=貂蝉}

LinkedHashMap

Queue队列

队列是一种先进先出的数据结构,元素在队列末尾添加,在队列头部删除。
Queue 接口扩展自 Collection,并提供插入、提取、检验等操作。
package com.jah.collection12;
import java.util.*;
public class TestQueue {
public static void main(String[] args) {
    Queue<String> queue = new LinkedList<String>(); 
    queue.offer("abc");
    queue.offer("cde");
    queue.offer("123");
    queue.offer("abc");
    System.out.println(queue); 
    System.out.println("queue.element():"+queue.element()); 
    System.out.println(queue); 
    System.out.println("queue.peek():"+queue.peek()); 
    System.out.println(queue); 
    System.out.println("queue.poll():"+queue.poll()); 
    System.out.println(queue); 
    System.out.println("queue.remove():"+queue.remove());
    System.out.println(queue); }
}

输出结果:

[abc, cde, 123, abc] 
queue.element():abc 
[abc, cde, 123, abc] 
queue.peek():abc 
[abc, cde, 123, abc] 
queue.poll():abc 
[cde, 123, abc] 
queue.remove():cde 
[123, abc]

Deque队列

接口 Deque,是一个扩展自 Queue 的双端队列,它支持在两端插入和删除元素,因为 LinkedList 类实现 了 Deque 接口,所以通常我们可以使用 LinkedList 来创建一个队列。

package com.jah.collection12;
import java.util.*;
public class TestDeque {
public static void main(String[] args) {
    Deque<String> queue = new LinkedList<String>(); 
    queue.offer("abc");
    queue.offer("cde");
    queue.offer("123");
    queue.offer("abc"); 
    queue.offerFirst("head"); 
    queue.offerLast("tail");
    System.out.println(queue);
    System.out.println("queue.removeFirst():"+queue.removeFirst());
    System.out.println(queue);
    System.out.println("queue.removeLast():"+queue.removeLast());
    System.out.println(queue);
} }

运行结果

[head, abc, cde, 123, abc, tail] 
queue.removeFirst():head 
[abc, cde, 123, abc, tail] 
queue.removeLast():tail
[abc, cde, 123, abc]

补充:PriorityQueue 类实现了一个优先队列,优先队列中元素被赋予优先级,拥有高优先级的先被删除

Stack栈

Stack 继承自 Vector,实现一个后进先出的堆栈

Stack 提供 5 个额外的方法使得 Vector 得以被当作堆栈使用。基本的 push 和 pop 方法,还有 peek 方法得到栈 顶的元素,empty 方法测试堆栈是否为空,search 方法检测一个元素在堆栈中的位置。

package com.jah.collection12;
import java.util.*;
public class TestDeque {
public static void main(String[] args) {
Stack<String> queue = new Stack<String>(); 
queue.add("abc");
queue.add("cde");
queue.push("123");
queue.push("xyz");
System.out.println(queue); 
System.out.println("queue.pop():"+queue.pop());
System.out.println(queue); 
    }
}

运行结果:

[abc, cde, 123, xyz] 
queue.pop():xyz 
[abc, cde, 123]

Collections工具类

是一个操作 Set、List 和 Map 等集合的工具类,提供了大量方法,对集合元素进行排序、查询和修改等操作,还提供了对集合对象设置不可变、对集合对象实现同步控制等方法

多线程

主要内容略过

辅助/补充内容

多线程各类状态通俗理解

假设你正在烹饪一道菜,这个菜需要经过多个步骤才能完成。新建状态可以类比为你去超市购买食材和厨具,就绪状态可以类比为你把食材和厨具准备好并开始烹饪,运行状态可以类比为你在烹饪菜肴的过程中,阻塞状态可以类比为你在等待烤箱完成烘烤的过程中,锁池状态可以类比为你在等待其他客人离开餐桌的过程中,死亡状态可以类比为菜肴已经烹饪完毕并被端上餐桌。

继承Thread实现多线程通俗讲解

1.创建一个新的类并继承Thread类:首先,你需要创建一个新的类,这个类会继承Thread类。在Java中,任何继承Thread类的类都被称为线程类。

public class MyThread extends Thread {  
    // 线程的执行逻辑将会在这里定义  
}

2.重写run()方法:在创建的线程类中,你需要重写run()方法。run()方法包含了线程的执行逻辑。当你调用start()方法启动线程时,线程会执行run()方法里的代码。

public class MyThread extends Thread {  
    @Override  
    public void run() {  
        // 这里是线程的执行逻辑  
        System.out.println("My thread is running!");  
    }  
}

3.启动线程:当你完成了线程类的定义,你就可以使用start()方法来启动线程了。注意,你不能直接调用run()方法,因为这只会执行run()方法里的代码,而不会启动一个新的线程。

MyThread myThread = new MyThread();  
myThread.start();

4.线程的状态:当线程启动后,它会进入就绪状态(Runnable)。当线程获得了CPU资源并开始执行时,它就进入了运行状态(Running)。当线程需要等待某个事件(如I/O操作)发生时,它就进入了阻塞状态(Blocked)。当线程正在等待某个锁释放时,它就进入了锁池状态(Waiting)。当线程执行完毕或被强制终止时,它就进入了死亡状态(Dead)。

5.注意事项:在Java中,我们不推荐直接继承Thread类来创建线程,因为这样做会导致我们的代码和Java的类层次结构紧密耦合。更好的做法是实现Runnable接口,并将实现放到实现类中。这样,我们可以更灵活地在不同的线程类中使用同一个Runnable实现。此外,Java还提供了其他高级的并发工具,如Executor框架、Fork/Join框架等,这些工具提供了更强大和灵活的并发处理能力。

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值