目录
1. 栈
一种先进后出的数据结构,若栈已空,继续出栈会抛出空栈异常
- 几种常用方法
- 入栈 : public E push(E item)
- 出栈 : public synchronized E pop()
- 观察栈顶元素 : public synchronized E peek()
import java.util.Stack;
/**
* 栈
* Author:qqy
*/
public class Test {
public static void main(String[] args) {
Stack<String> stack = new Stack<>();
System.out.println("当前栈是否为空:" + stack.isEmpty());
//入栈
stack.push("Java");
stack.push("C++");
stack.push("PHP");
System.out.println("当前栈是否为空:" + stack.isEmpty());
System.out.println("当前栈的元素个数:" + stack.size());
//观察栈顶
System.out.println("栈顶是否是PHP:" + "PHP".equals(stack.peek())); //true
//出栈
System.out.println(stack.pop());//PHP
System.out.println(stack.pop());//C++
System.out.println(stack.pop());//Java
//EmptyStackException
// System.out.println(stack.pop());//?
while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
}
}
2. 队列
先进先出
- 几种常用方法
- 入队列 : public E add(E e)
- 出队列: public E poll();
- 观察队列头元素 : public E peek()
import java.util.LinkedList;
import java.util.Queue;
/**
* Queue队列的基本使用
* Author:qqy
*/
public class Test1 {
public static void main(String[] args) {
//LinkedList 左边类型 Queue
Queue<String> queue = new LinkedList<>();
System.out.println("队列的元素是否为空:" + queue.isEmpty());
//入队列 add
queue.add("Java");
queue.add("C++");
System.out.println("队列的元素是否为空:" + queue.isEmpty());
queue.add("PHP");
System.out.println("队列的元素数量:" + queue.size());
//查看队头
System.out.println("队头元素时:PHP " + "PHP".equals(queue.peek()));//false
//出队列 poll
System.out.println(queue.poll());//Java
System.out.println(queue.poll());//C++
System.out.println(queue.poll());//PHP
System.out.println(queue.poll());//null
}
}
- 队列在整个的操作之中可以起到一个缓冲的作用,可以利用队列修改之前的生产者和消费者程序模型。生产者和消费者的能力(速度)不匹配,采用队列的方式存储生产消费的资源(元素),解耦生产者和消费者的实现逻辑
import java.util.LinkedList;
import java.util.Queue;
/**
* 生产者、消费者模型
* Author:qqy
*/
public class Queue1 {
public static void main(String[] args) {
Queue<String> queue1=new LinkedList<>();
//生产者
new Thread(new Runnable() {
{
System.out.println("生产者线程启动");
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(800);
//生产数据
String data = String.valueOf(Math.random());
System.out.println("生产" + data);
queue1.add(data);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
//消费者
new Thread(() -> {
while(true) {
try {
Thread.sleep(500);
System.out.println("消费" + queue1.poll());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
3. Properties属性文件操作
属性文件(资源文件)的定义:*.properties文件
属性类:Properties
- 在这种文件里面其内容的保存形式为"key = value",想编辑其内容则需要通过Properties类来完成,这个类是专门做属性处理的。
public class Properties extends Hashtable<Object,Object>
- 几种常用方法
- 设置属性 : public synchronized Object setProperty(String key, String value)
- 取得属性 : public String getProperty(String key),如果没有指定的key则返回null
- 取得属性 : public String getProperty(String key, String defaultValue),如果没有指定的key则返回默认值
- 保存属性: public void store(OutputStream out, String comments) throws IOException
- 读取属性: public synchronized void load(InputStream inStream) throws IOException
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* properties基本使用
* Author:qqy
*/
public class Test12 {
public static void main(String[] args) {
// *.properties -> Properties
//读取文件:load -> Properties InputStream/Reader
//写入文件:store -> *.properties OutputStream/Writer
Properties properties = new Properties();
try {
//1.通过FileInputStream,缺点:当文件在源代码中,当代码挪动后,文件路径改变
// properties.load(new FileInputStream("E:\JAVA\code\19.Collection\Collection\src\com\qqy\hello.properties"));
//2.通过ClassLoader类加载器的方式读取属性文件时,指定包路径
InputStream inputStream = Test12.class.getClassLoader().getResourceAsStream("com/qqy/hello.properties");
properties.load(inputStream);
//1.getProperty(key)
//2.getProperty(key,defaultValue)
System.out.println(properties.get("c++"));
System.out.println(properties.getProperty("c++"));
System.out.println(properties.getProperty("php")); //null
System.out.println(properties.getProperty("php", "PHP是最好的语言"));
//赋值
//1.put
//2.setProperty (建议使用setProperty)
properties.put("php", "PHP is best");
properties.setProperty("Go", "Go is better");
//存储
properties.store(new FileOutputStream(
"E:\\JAVA\\code\\19.Collection\\Collection\\src\\com\\qqy\\hello1.properties"
), "写入数据");
} catch (IOException e) {
e.printStackTrace();
}
}
}
4. Collections工具类
Collections是一个集合操作的工具类,包含有集合反转、排序等操作
import java.util.*;
/**
* Collections工具类
* Author:qqy
*/
public class Test13 {
public static void main(String[] args) {
//ArrayList打印a——z
List<String> data = new ArrayList<>();
for (int i = 65; i < 123; i++) {
data.add(String.valueOf((char) i));
}
System.out.println("原始数据:" + data);
//反转方法
Collections.reverse(data);
System.out.println("反转之后:" + data);
//查找
System.out.println(data.get(0));
System.out.println(data.size());
//如果它包含在列表中,搜索关键字的索引;否则, (-(insertion point) - 1)
//insertion point -> 第一个大于查找对象的元素在数组中的位置,如果数组中所有的元素值都小于要查找的对象,“插入点”就等于 Arrays.size()。
//binarySearch()
//使用二叉搜索算法搜索指定对象的指定列表。 该列表必须根据指定的比较器(如sort(List)方法)按升序排序
//如果没有排序,结果是未定义的。 如果列表包含与指定对象相等的多个元素,则不能保证将找到哪个元素。
//不能依赖于添加的顺序,最好自己提供排序算法,int类型不需要指定比较器
int index = Collections.binarySearch(data, "z"); // -(58)-1
System.out.println("查看z的下标:" + index);
System.out.println("查看A的下标:" + Collections.binarySearch(data, "A")); //-0-1
//乱序
Collections.shuffle(data);
System.out.println(data);
//1.非同步集合-> 同步集合
//2.集合 -> 不可修改
Map<String, String> map = new HashMap<>();
System.out.println(map.put("1", "Java"));
//UnmodifiableMap将Map包装成一个不可修改的Map
map = Collections.unmodifiableMap(map);
//不能修改
// map.put("2", "C++");
}
}
5. Stream流
-
5.1 Collection改进
几个常用的方法:
- forEach()输出支持: default void forEach(Consumer<? super T> action)
- 取得Stream数据流对象: default Stream <E> stream()
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
/**
* forEach
* Author:qqy
*/
public class TestCollection {
public static void main(String[] args) {
//forEach 来自 Iterable,被Collection继承
List<String> list = new ArrayList<>();
Collections.addAll(list, "Java", "C++", "Python", "JavaScript");
//匿名内部类
list.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
//Lambda表达式
list.forEach(s-> System.out.println(s));
//方法引用
list.forEach(System.out::println);
}
}
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* Stream流
* Author:qqy
*/
public class Test14 {
public static void main(String[] args) {
//stream 来自 Collection
List<String> list = new ArrayList<>();
Collections.addAll(list, "Java", "C++", "Python", "JavaScript");
//返回所有Stream流中所有元素的个数
System.out.println(list.stream().count()); //4
//旧方法
List<String> lists = new ArrayList<>();
for (String item : list) {
if (item.contains("Java")) {
lists.add(item.toUpperCase());
}
}
System.out.println(lists);
//利用stream的新方法
List<String> newList = list
.stream()
.filter(s -> s.contains("Java"))
.map(s -> s.toUpperCase())
.collect(Collectors.toList()); //汇总到集合
System.out.println(newList);
//直接打印
list.stream()
.filter(s -> s.contains("Java")) //返回此流中所有包含"Java"的元素组成的流
.map(s-> s.toUpperCase()) //
.forEach(System.out::println); //打印
}
}
-
5.2 Stream操作
- 数据统计
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 符合添加的元素个数统计
* Author:qqy
*/
public class Test16 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Collections.addAll(list, "Java", "C++", "Python", "JavaScript");
Long count = list.stream()
.filter(s -> s.contains("Java"))
.count();
System.out.println("包含Java的元素有:" + count+"个");
}
}
- 收集器:public <R, A> R collect(Collector<? super T, A, R> collector)
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* 利用集合,将int转为String
* Author:qqy
*/
public class Test15 {
public static void main(String[] args) {
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
intList.add(3);
List<String> stringList = intList.stream().map(integer -> String.valueOf(integer))
.collect(Collectors.toList());
System.out.println(stringList);
}
}
- 在Stream接口中重点有两个操作方法:
- 设置取出最大内容: public Stream limit(long maxSize);
- 跳过的数据量: public Stream skip(long n);
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* skip与limit方法
* Author:qqy
*/
public class Test17 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Collections.addAll(list, "1、Java", "2、C++", "3、Python", "4、JavaScript", "5、Nginx", "6、Tomcat");
//没有数据显示
// list.stream()
// .skip(7)
// .limit(1)
// .forEach(System.out::println);
//跳过1个,取3个,打印其中包括"Java"的
/*
以下3个方法不会立即调用,当流式操作的过程中调用了终结方法(foreach -> 返回void,不再返回流),才会执行
优点:
1.不用每次都遍历几何元素
2.高效进行处理
*/
list.stream()
.skip(1)
.limit(3)
.filter(s -> s.contains("Java"))
.forEach(System.out::println);
}
}
-
5.3 MapReduce基础模型
Map: 处理数据,指的是针对于数据进行先期的操作处理
Reduce: 统计分析数据
import java.util.*;
import java.util.function.DoubleBinaryOperator;
import java.util.function.DoubleSupplier;
import java.util.stream.Collectors;
/**
* 简单的数据统计操作
* Author:qqy
*/
public class TestMapReduce {
public static void main(String[] args) {
List<Order> orderList = new ArrayList<>();
orderList.add(new Order("Iphone", 8999.99, 10));
orderList.add(new Order("外星人笔记本", 12999.99, 5));
orderList.add(new Order("MacBookPro", 18999.99, 5));
orderList.add(new Order("Java从入门到放弃.txt", 9.99, 20000));
orderList.add(new Order("中性笔", 1.99, 200000));
orderList.add(new Order("中性笔", 2, 20));
orderList.add(new Order("外星人笔记本", 1000, 1));
price(orderList);
statistics(orderList);
grouping(orderList);
optimize(orderList);
}
//计算金额总和
public static void price(List<Order> orderList){
double total = 0.0D;
for (Order order : orderList) {
total += order.getPrice() * order.getAmount();
}
System.out.println("总金额是:" + total);
//fork-join -> Java提供的并发处理
//map - reduce 进行的总额计算
double totalPrice = orderList
.stream()
//求出每一个订单的金额,并转为double流,eg:[10.4,22.4,18.5]
.mapToDouble(o -> o.getPrice() * o.getAmount())
/*
OptionalDouble reduce(DoubleBinaryOperator op);
public interface DoubleBinaryOperator {
double applyAsDouble(double left, double right);
}
DoubleStream 里面的每个元素求和
left right
left-> sum = 0 right -> x=10.4
sum(left) 10.4(right) -> sum= left + right = 0 + 10.4
sum(left) 22.4(right) -> sum = left + right = 10.4 + 22.4
*/
.reduce(new DoubleBinaryOperator() {
@Override
public double applyAsDouble(double left, double right) {
return left+right;
}
})
//不存在,返回给定的值;存在,返回value
//等价于orElse(0);
.orElseGet(new DoubleSupplier() {
@Override
public double getAsDouble() {
return 0;
}
});
System.out.println("订单总价:" + totalPrice);
}
//map-reduce 统计分析
public static void statistics(List<Order> orderList){
DoubleSummaryStatistics summary= orderList.stream()
.mapToDouble(o -> o.getPrice() * o.getAmount())
.summaryStatistics();
//有多少订单,最大订单,最小订单,总额,平均值
System.out.println("数量:" + summary.getCount());
System.out.println("最大值:" + summary.getMax());
System.out.println("最小值:" + summary.getMin());
System.out.println("总和:" + summary.getSum());
System.out.println("平均值:" + summary.getAverage());
}
//自己实现订单分组(按title分组)
public static void grouping(List<Order> orderList) {
//key -> title,value -> 订单信息
Map<String, List<Order>> map = new HashMap<>();
for (Order order : orderList) {
if (map.containsKey(order.getTitle())) {
map.get(order.getTitle()).add(order);
} else {
List<Order> orders = new ArrayList<>();
orders.add(order);
map.put(order.getTitle(), orders);
}
}
System.out.println(map);
//计算title相同的订单金额
Map<String, Double> doubleMap = new HashMap<>();
for (Map.Entry<String, List<Order>> entry : map.entrySet()) {
String title = entry.getKey();
List<Order> orders = entry.getValue();
double sum = 0.0D;
for (Order o : orders) {
sum += o.getPrice() * o.getAmount();
}
doubleMap.put(title, sum);
}
System.out.println(doubleMap);
}
public static void optimize(List<Order> orderList){
//Stream , group by , foreach
Map<String, Double> doubleMap = new HashMap<>();
orderList.stream()
//利用groupingBy()订单分组
.collect(Collectors.groupingBy(Order::getTitle))
.forEach((k, v) -> {
//String k
//List<Order> v
//计算金额总和
double total = v.stream()
.mapToDouble(o -> o.getPrice() * o.getAmount())
.reduce((sum, x) -> sum + x)
.orElse(0);
doubleMap.put(k, total);
});
System.out.println(doubleMap);
}
}
public class Order {
private String title ;
private double price ;
private int amount ;
public Order(String title, double price, int amount) {
this.title = title;
this.price = price;
this.amount = amount;
}
public String getTitle() {
return title;
}
public double getPrice() {
return price;
}
public int getAmount() {
return amount;
}
@Override
public String toString() {
return "Order{" +
"title='" + title + '\'' +
", price=" + price +
", amount=" + amount +
'}';
}
}