zoukankan      html  css  js  c++  java
  • 集合(下)

    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接口
    DequeDouble 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实现类
    HashMapMap最常使用的实现类。
    遍历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、LinkedHashMapTreeMap
    LinkedHashMap继承自HashMapTreeMap 继承自 AbstractMap
    在特征上与LinkedHashSetTreeSet类似。
    NavigableMapSortedMap的子接口。
    TreeMapNavigableMap的实现类。

    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));
    	}
    
    }
    

      


     

  • 相关阅读:
    牛客(47)求1+2+3+...+n
    牛客(48)不用加减乘除做加法
    【推荐】可编程的热键 AutoHotkey
    【Web】js 简单动画,犯了低级错误
    【分享】JDK8u241 win x64度盘下载
    【Web】开始学Web开发!
    【数组】深析 “数组名称”
    【基础向】浅析 "多(二)维数组" 的三种引用方法
    【一个小错误】通过数组指针引用数组成员
    【网络通信教程】windows 下的 socket API 编程(TCP协议)
  • 原文地址:https://www.cnblogs.com/liuwei6/p/6574717.html
Copyright © 2011-2022 走看看