1、Queue接口
Queue接口是Collection接口的子接口。
Queue接口表示一个队列,分为队头与队尾。通常实现先进 先出的原则( FIFO),但这不是必须的。
例如,
PriorityQueue是根据优先级来进行排序的。队列会根据具体的实现来组织与管理新加入元素的位置。无论 哪种实现方式,删除(获取)元素时,会删除(获取)队 列头部的元素。
package day15;
import java.util.LinkedList;
import java.util.Queue;
/*
* Queue接口
* 接口中的方法可以分成两组:
* 一组:add remove element
* 二组:offer poll peek
* 第一组在操作失败时,会产生异常。
* 第二组在操作失败时,不会产生异常,而是返回特定的值。
* 优先考虑使用第二组方法。
*
* Queue接口关于null值。
* Queue接口中不允许加入null值。因为null值是作为poll与peek
* 在操作失败时的返回值。
* 对于LinkedList实现类,允许加入null值,这是一种特例,因为
* 要做到兼容以前的程序。(我们要尽可能回避这种特例)
*/
public class QueueMethod {
public static void main(String[] args) {
Queue<Integer> q = new LinkedList<>();
// 向队列中加入元素。如果加入失败,抛出异常。
q.add(1);
// 向队列中加入元素。如果加入失败,返回false。
// (不会产生异常。)
q.offer(1);
// 删除并返回队列头部的元素。如果删除失败,抛出异常。
// q.remove();
// 删除并返回队列头部的元素。如果删除失败,返回null。
// q.poll();
// 获取并返回队列头部的元素(不会删除该元素)。如果
// 获取失败,抛出异常。
// q.element();
// 获取并返回队列头部的元素(不会删除该元素)。如果
// 获取失败,返回null。
// q.peek();
// 一种特例。
q.add(null);
}
}
2、PriorityQueue实现类
Queue接口的一个特殊的实现类,不是按照先进先出的原则, 而是根据特定机制对元素进行排序处理。排序的规则可能是:
自然排序
指定排序
说明:
PriorityQueue实现类没有元素的限制。
PriorityQueue对内部元素的排序不会体现在集合的遍历上。
/*
* PriorityQueue优先级队列
*/
package day15;
import java.util.PriorityQueue;
import java.util.Queue;
/*
* PriorityQueue是Queue的一个特殊实现类,其不是按照
* 传统的先进先出的原则实现的,而是按照元素的优先级在内部
* 进行排序。注意:内部的元素排序不会表现在元素的遍历上。
*
* 对于无参的构造器,使用自然排序。
* 也可以传递一个比较器。
*/
public class PriorityQueueTest {
public static void main(String[] args) {
// Queue<Integer> q = new PriorityQueue<>();
Queue<Integer> q = new PriorityQueue<>((a, b) -> b - a);
// q.add(null);
q.offer(100);
q.offer(20);
q.offer(15);
q.offer(68);
// 在使用PriorityQueue对元素进行遍历时,
// 不保证任何遍历顺序(遍历顺序没有任何保证)。
// q.forEach(System.out::println);
while (q.size() > 0) {
System.out.println(q.poll());
}
}
}
3、Deque接口
Deque( Double Ended Queue)接口是Queue接口的子接口。
Deque接口表示一个双端的队列,即可以从队列的两端增加 与删除(获取)元素。
Deque接口可以同时实现队列( FIFO)与堆栈( LIFO)的功 能。
Deque接口有两个常用的实现类:
ArrayDeque
LinkedList
package day15;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
public class DequeMethod {
public static void main(String[] args) {
// Deque<Integer> dq = new LinkedList<>();
Deque<Integer> dq = new ArrayDeque<>();
// 从队头加入元素。失败时会产生异常。
dq.addFirst(1);
// 从队尾加入元素。
dq.addLast(1);
// 从队头加入元素。失败时不会产生异常,而是返回false。
dq.offerFirst(1);
// 从队尾加入元素。
dq.offerLast(1);
// 删除并返回队列头部的元素。
dq.removeFirst();
// 删除并返回队列尾部的元素。
dq.removeLast();
// 删除并返回队列头部的元素。失败时不会产生异常,而是返回null。
dq.pollFirst();
// 删除并返回队列尾部的元素。失败时不会产生异常,而是返回null。
dq.pollLast();
// 获取队列头部的元素(不会删除该元素)。
dq.getFirst();
// 获取队列尾部的元素(不会删除该元素)。
dq.getLast();
// 获取队列头部的元素(不会删除该元素)。失败时不会产生
// 异常,而是返回null。
dq.peekFirst();
// 获取队列尾部的元素(不会删除该元素)。失败时不会产生
// 异常,而是返回null。
dq.peekLast();
// 删除队列中首次出现的元素(参数指定)。删除成功返回true,
// 否则返回false。
dq.removeFirstOccurrence(2);
// 删除队列中最后一次出现的元素(参数指定)。删除成功返回true,
// 否则返回false。
dq.removeLastOccurrence(1);
// 向队列头部加入元素。(作为堆栈使用)
dq.push(1);
// 删除队列头部的元素。(作为堆栈使用)
dq.pop();
}
}
4、Map接口
package day15;
import java.util.HashMap;
import java.util.Map;
public class MapTest {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
// 加入键值对,返回该键之前绑定的值。如果该键之前没有
// 绑定值,则返回null。
System.out.println(map.put(1, "abc"));
// map中的键值不能重复,如果加入了重复了键值,
// 则该键值会绑定后来的value。
System.out.println(map.put(1, "cdf"));
// 获取键(key)绑定的值(value)
System.out.println(map.get(1));
}
}
5、HashMap实现类
HashMap是Map最常使用的实现类。
遍历Map的方式: 使用keyset 使用entrySet 使用forEach
package day15;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MapMethod {
public static void main(String[] args) {
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 100);
map.put(2, 200);
// 返回map中键值对的数量。
// System.out.println(map.size());
// 判断map是否为空(键值对数量是否为0),
// 如果为空,返回true,否则返回false。
// System.out.println(map.isEmpty());
// 判断map中是否含有参数指定的key。含有返回true,
// 否则返回false。
// System.out.println(map.containsKey(1));
// 判断map中是否含有参数指定的value。含有返回true,
// 否则返回false。
// System.out.println(map.containsValue(200));
// 删除与参数指定键值相等的键值对。返回该键所绑定
// 的value值。如果该键没有绑定value值,返回null。
// System.out.println(map.remove(10));
Map<Integer, Integer> map2 = new HashMap<>();
map2.put(3, 300);
map2.put(4, 400);
// 将参数map中所有的键值对加入到当前map中。
map.putAll(map2);
// System.out.println(map);
// 清空map。(删除map中所有的键值对)
// map.clear();
System.out.println(map);
// 返回一个set,该set中包含map中所有的key值。
Set<Integer> set = map.keySet();
// set.forEach(System.out::println);
// 返回一个Collection,该Collection中包含
// map中所有的value值。
Collection<Integer> c = map.values();
// c.forEach(System.out::println);
// 返回一个set,该set中存放map中所有的Entry(键值对)。
Set<Entry<Integer, Integer>> entrys = map.entrySet();
}
}
package day15;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/*
* 对Map进行遍历
*/
public class MapTraverse {
public static void main(String[] args) {
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 100);
map.put(2, 200);
map.put(3, 300);
map.put(4, 500);
// 1 使用keySet方法。
Set<Integer> keys = map.keySet();
keys.forEach(k -> System.out.println(k + ":" + map.get(k)));
// 2使用entrySet方法
Set<Entry<Integer, Integer>> entry = map.entrySet();
entry.forEach(e -> System.out.println(e.getKey() + ":" + e.getValue()));
map.forEach((k, v) -> System.out.println(k + ":" + v));
}
}
6、LinkedHashMap与TreeMap
LinkedHashMap继承自HashMap。 TreeMap 继承自 AbstractMap。
在特征上与LinkedHashSet与TreeSet类似。
NavigableMap是SortedMap的子接口。
TreeMap是NavigableMap的实现类。
package day15;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
public class LinkedHashMapTest {
public static void main(String[] args) {
// Map<String, Integer> map = new HashMap<>();
Map<String, Integer> map = new LinkedHashMap<>();
map.put("addf", 11);
map.put("zdfeaa", 22);
map.put("fous", 33);
map.put("onensdf", 44);
map.put("tisoe", 55);
/*
* 与HashSet相同,HashMap在获取元素时,也不能保证 获取的顺序与元素加入时的顺序一致。实际上,HashSet
* 底层就是使用HashMap来实现的。 如果期望获取元素的顺序与元素加入时的顺序一致,可以使用 LinkedHashMap来实现。
*/
map.forEach((k, v) -> System.out.println(k + ":" + v));
}
}
package day15;
import java.util.Map;
import java.util.TreeMap;
public class TreeMapTest {
public static void main(String[] args) {
// TreeMap是根据key值进行排序的。
// Map<Integer, String> map = new TreeMap<>();
Map<Integer, String> map = new TreeMap<>((a, b) -> b - a);
// 可以指定比较器,如果没有提供比较器,则使用自然排序。
map.put(1, "sdf");
map.put(5, "ccc");
map.put(-2, "csa");
map.forEach((k, v) -> System.out.println(k + ":" + v));
}
}
7、聚合操作
流是一组元素的序列。集合对象可以通过相关方法获得流。
通过集合对象的流,就可以在流的基础上对集合元素进行相 关的操作,如过滤,映射,迭代等,该操作称为流操作,也 称为聚合操作。
流管道为一系列顺序的聚合操作。管道由数据源(数组,集 合, IO通道等), 中间操作( 0或多个)与终端操作( 1个) 组成
聚合操作可以分为中间操作与终端操作。
聚合操作聚合操作的中间操作会产生一个新的流,供后续中 间操作或终端操作使用。而终端操作不会再产生流。
中间操作是惰性的,这样可以在一定程度上提高性能。流只 有在终端操作开始时才会执行。
中间操作可以分为有状态操作与无状态操作。
一旦执行终端操作,则整个流被消费掉,不可再次使用。
8、案例
输出集合中所有的元素,可以使用:
forEach方法
聚合操作的forEach操作。
package day15;
import java.util.ArrayList;
import java.util.Collection;
public class ForEach {
public static void main(String[] args) {
Collection<Integer> c = new ArrayList<>();
for (int i = 0; i < 50; i++) {
c.add(i);
}
// c.forEach(System.out::println);
// c.stream().forEach(System.out::println);
// c.stream().filter(t -> t > 3).forEach(System.out::println);
// c.forEach(System.out::println);
// c.stream().forEach(System.out::println);
c.parallelStream().forEach(System.out::println);
}
}
9、聚合操作与迭代器
不同之处:
聚合操作从流中处理数据,其不会改变底层的数据源。而迭 代器则对集合进行操作,会改变集合。
聚合操作使用内部迭代方式,而迭代器使用外部迭代进行处 理。
聚合操作(内部迭代)可以根据需要并行处理数据,而迭代 器仅能进行顺序迭代
10、中间操作
中间操作
filter
map / mapToInt / mapToLong / mapToDouble
distinct
sorted
peek
limit
skip
11、缩减操作
将流中的内容合并,作为一个值返回,这种操作成为缩减操作。
缩减操作如下:
max
min
average
sum
count
reduce
collect
说明:缩减操作都是终端操作。
package day15;
import java.util.*;
public class AggOP {
public static void main(String[] args) {
Collection<Integer> c = new ArrayList<>();
c.add(200);
c.add(-2);
c.add(16);
c.add(28);
c.add(-2);
// c.stream().filter(t -> t > 20).forEach(System.out::println);
// c.stream().distinct().forEach(System.out::println);
// c.stream().filter(t -> t >
// 20).distinct().sorted().forEach(System.out::println);
// c.stream().peek(System.out::println).forEach(System.out::println);
// c.stream().limit(30).forEach(System.out::println);
// c.stream().skip(2).forEach(System.out::println);
Collection<Person> cp = new ArrayList<>();
cp.add(new Person("1", 20));
cp.add(new Person("2", 10));
cp.add(new Person("3", 14));
cp.add(new Person("4", 24));
cp.add(new Person("1", 20));
// cp.stream().map(p -> p.getName()).forEach(System.out::println);
// cp.stream().map(p -> p.getAge()).forEach(System.out::println);
// cp.stream().mapToInt(p -> p.getAge()).forEach(System.out::println);
// cp.stream().distinct().forEach(System.out::println);
int max = cp.stream().mapToInt(Person::getAge).max().getAsInt();
int min = cp.stream().mapToInt(Person::getAge).min().getAsInt();
double avg = cp.stream().mapToInt(Person::getAge).average().getAsDouble();
int sum = cp.stream().mapToInt(Person::getAge).sum();
long count = cp.stream().mapToInt(Person::getAge).count();
// System.out.println(max);
// System.out.println(min);
// System.out.println(avg);
// System.out.println(sum);
// System.out.println(count);
// int x =
// cp.stream().mapToInt(Person::getAge).reduce(Math::max).getAsInt();
// int x =
// cp.stream().mapToInt(Person::getAge).reduce(Integer::sum).getAsInt();
// int x = cp.stream().mapToInt(Person::getAge).reduce(100, Math::max);
// System.out.println(x);
// List<Integer> list = cp.stream().filter(p -> p.getAge() >
// 15).mapToInt(p -> p.getAge()).distinct().sorted()
// .collect(() -> new ArrayList<>(), (t, e) -> t.add(e), (a, b) ->
// a.addAll(b));
List<Integer> list = cp.stream().filter(p -> p.getAge() > 15).mapToInt(p -> p.getAge()).distinct().sorted()
.collect(ArrayList::new, List::add, List::addAll);
list.forEach(System.out::println);
}
}
class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
12、Arrays类
Arrays类是一个工具类,提供对数组的一系列操作。
Arrays类的排序方法( sort)也可以使用自然排序,也可以 指定排序规则。
asList方法
package day15;
import java.util.Arrays;
import java.util.List;
public class AsList {
public static void main(String[] args) {
int[] x = { 1, 2, 3, 5, 8 };
List<int[]> list = Arrays.asList(x);
System.out.println(list.size());
Integer[] y = { 1, 2, 3, 5, 8 };
List<Integer> list2 = Arrays.asList(y);
System.out.println(list2.size());
// 通过asList方法返回的List是不能改变的。
// 因为数组长度是不能改变的。
// list2.add(100);
}
}
13、Collections类
Collections类提供了一系列操作集合的方法。所有的方法都是 静态的。
sort
binarySearch
reverse
shuffle
fill
min / max
frequency
package day15;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsMethod {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(500);
list.add(-20);
list.add(78);
list.add(222);
list.add(78);
// 对List进行排序(自然排序)。
// Collections.sort(list);
// 对List进行排序(比较器)。
// Collections.sort(list, (a, b) -> b - a);
// 对于排序,List本身也能够进行排序
// list.sort(null);
// list.sort((a, b) -> b - a);
// list.forEach(System.out::println);
// 在List中查询指定的关键字,如果找到,返回关键字的
// 索引,如果没有找到,返回-插入点-1。
// 要求:List必须是升序排列的,否则结果是不确定的。
// int index = Collections.binarySearch(list, 333);
// System.out.println(index);
// 对List的顺序实现翻转。
// Collections.reverse(list);
// list.forEach(System.out::println);
// 对List进行洗牌操作。
// Collections.shuffle(list);
// list.forEach(System.out::println);
// 使用参数指定的元素对List进行填充。
// Collections.fill(list, 90);
// list.forEach(System.out::println);
// 返回集合中的最大值(自然排序)
// int x = Collections.max(list);
// System.out.println(x);
// 返回集合中的最大值(比较器)
// int x = Collections.max(list, (a, b) -> b - a);
// System.out.println(x);
// 返回集合中的最小值(自然排序)
// System.out.println(Collections.min(list));
// 返回集合的最小值(比较器)
// System.out.println(Collections.min(list, (a, b) -> b - a));
// 返回关键字(第2个参数)在集合中(第1个参数)出现的频率。
System.out.println(Collections.frequency(list, 78));
}
}