Java——集合类(栈、队列、Collections和Stream流)

目录

1. 栈

2. 队列

3. Properties属性文件操作 

4. Collections工具类

5. Stream流

5.1 Collection改进

5.2 Stream操作

5.3 MapReduce基础模型


1. 栈

一种先进后出的数据结构,若栈已空,继续出栈会抛出空栈异常

  • 几种常用方法
  1. 入栈 : public E push(E item)
  2. 出栈 : public synchronized E pop()
  3. 观察栈顶元素 : 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. 队列

先进先出

  • 几种常用方法
  1. 入队列 : public E add(E e)
  2. 出队列: public E poll();
  3. 观察队列头元素 : 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>
  • 几种常用方法
  1.  设置属性 : public synchronized Object setProperty(String key, String value)
  2.  取得属性 : public String getProperty(String key),如果没有指定的key则返回null
  3.  取得属性 : public String getProperty(String key, String defaultValue),如果没有指定的key则返回默认值
  4.  保存属性: public void store(OutputStream out, String comments) throws IOException
  5.  读取属性: 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改进

几个常用的方法:

  1.  forEach()输出支持: default void forEach(Consumer<? super T> action)
  2.  取得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接口中重点有两个操作方法:
  1. 设置取出最大内容: public Stream limit(long maxSize);
  2. 跳过的数据量: 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 +
                '}';
    }
}

猜你喜欢

转载自blog.csdn.net/qq_42142477/article/details/87891155
今日推荐