JAVASE15

JAVASE15

一、TreeMap

TreeSet底层就是由TreeMap维护的

底层结构: 红黑树
特点: 有序(默认升序排序),存放存储与内部真实存储顺序是不一致的

注意: 以后什么功能|结构能够实现排序的,想到比较器:指定比较规则

去重排序: 根据key实现去重与排序
key中存放的数据的类型->1)实现内部比较器 2)实现外部比较器

我们先写一User类

public class User implements Comparable<User>{
    private String username;
    private int password;

    public User() {
    }

    public User(String username, int password) {
        this.username = username;
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public int getPassword() {
        return password;
    }

    public void setPassword(int password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "Person{" +
                "username='" + username + '\'' +
                ", password=" + password +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return password == user.password &&
                Objects.equals(username, user.username);
    }

    @Override
    public int hashCode() {
        return Objects.hash(username, password);
    }

    //内部比较方式
    @Override
    public int compareTo(User o) {
        return this.getUsername().compareTo(o.getUsername());
    }
}

然后开始存储

public class TreeMapDemo01 {
    public static void main(String[] args) {
        //默认根据User类的内部比较器提供的比较方式进行比较排序
        //TreeMap<User,String> map = new TreeMap<>();

        //指定使用某种外部比较规则
        TreeMap<User,String> map = new TreeMap<>((o1, o2) -> o1.getPassword()-o2.getPassword());

        //map.put(null,null);  //treemap中存储键值对key不能为null

        //存储数据,在存储的时候才会比较,排序
        map.put(new User("阿浪",111),"新浪");
        map.put(new User("阿汤",122),"腾讯");
        map.put(new User("阿哥",133),"斗鱼");
        map.put(new User("阿笙",144),"拼多多");
        map.put(new User("阿烨",144),"点淘app");

        System.out.println(map);
    }
}

二、Properties

Properties为Hashtable的子类,要求键与值只能为字符串 ,不能为null,常与配置文件(与外界交互的信息) 即内存与存储介质(文件、数据库、网络、服务器内存等)交互

​ properties根式作为配置文件的格式存在,键值对 都是字符串,简单
​ 程序从properties文件中读取数据:
​ void load(InputStream inStream) 从输入字节流中读取属性列表(键和元素对)。

.properties文件

userName=庄周
passWord=12345678
public class PropertiesDemo02 {
    public static void main(String[] args) throws IOException {
        Properties pro = new Properties();

        //通过properties对象从配置文件中读取数据
        //指定从哪一个文件,通过哪个流加载
        pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));

        System.out.println(pro.getProperty("userName"));
        System.out.println(pro.getProperty("passWord"));
    }
}

注意:这里如果我们的userName输入的是中文,我们需要设置好编码格式不然在java中输出的就是类似于乱码的存在。

三、Collections

Collections 与 Collection 之间的区别:
Collection 集合体系的上层接口
Collections 操作集合数据的工具类 , 与 Array很像

查找的方法查找特定对象
使用前提: 升序排序

HashMap线程不安全问题:
1.Hashtable类型,线程安全的HashMap
Hashtable是同步的。 如果不需要线程安全实现,建议使用HashMap代替Hashtable 。 如果需要线程安全的高度并发实现,则建议使用ConcurrentHashMap代替Hashtable 。
2.Collections -> static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) 返回由指定映射支持的同步(线程安全)映射。
3.juc包(高级并发编程包) - > ConcurrentHashMap 线程安全的哈希表—>推荐,安全性好效率高

public class CollectionsDemo01 {
    public static void main(String[] args) {
        //sort
        //List<Integer> list = List.of(5,1,2,6,4,3);
        List<Integer> list = new ArrayList<>();
        list.add(3);
        list.add(5);
        list.add(1);
        list.add(4);
        list.add(2);

        System.out.println(list);
        //升序
        Collections.sort(list);

        System.out.println(list);

        List<User> list2 = new ArrayList<>();
        list2.add(new User("", 19));
        list2.add(new User("", 18));
        list2.add(new User("", 20));

        Collections.sort(list2, (o1, o2) -> o2.getPassword() - o1.getPassword());

        System.out.println(list2);

        // void shuffle(List) //对List容器内的元素进行随机排列
        // Collections.shuffle(list);

        System.out.println(list);

        //reverse
        //Collections.reverse(list);
        System.out.println(list);

        //void fill(List, Object)
        //Collections.fill(list,111);
        System.out.println(list);

        System.out.println(Collections.binarySearch(list, 6));//-插入点-1
    }
}

四、Thread

线程(英语:thread)是操作系统**能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

​ 多线程优点: 资源利用率更好;程序设计在某些情况下更简单;程序响应更快

进程与线程的区别

区别进程线程
根本区别作为资源分配的单位调度和执行的单位
开销每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的的开销线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程由独立运行栈和程序计数器(PC),线程切换的开销小
所处环境在操作系统中能同时运行多个任务(程序)在同一应用程序中有多个顺序流通时执行
分配内存系统在运行的时候会为每个进程分配不同的内存区域线程间共享进程的所有资源,每个线程只有自己的堆栈和局部变量,线程有CPU独立调度执行,在多CPU环境下就允许多个线程同时运行
包含关系没有线程的进程可以看做单线程,如果一个进程拥有多个线程,则执行过程不是一条线的,而是多余线(线程)共同完成的线程是进程的一部分,所以线程有的时候会被称为是轻量级进程或轻权进程

创建线程+开启线程:
1.继承Thread,重写run() + start()
2.实现Runnable,重写run()方法,方法的内部定义线程体 + start()
接口: 可以多实现,类只能单继承
可以资源共享

第一种方法

public class ThreadDemo01 extends Thread{
    public static void main(String[] args) {
        //创建线程
        ThreadDemo01 th = new ThreadDemo01();
        //开启线程
        th.start();
        //th.run(); 方法的调用

        //主线程
        for(int i=1;i<=20;i++){
            System.out.println("一边讲课");

            /*休息10ms*/
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /*
        定义线程体代码
     */
    @Override
    public void run() {
        for(int i=1;i<=20;i++){
            System.out.println("一边喝水");

            /*休息10ms*/
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

第二种方法

实现Runnable接口,重写run()方法 + start() 开启线程
接口可以多实现
可以实现资源共享

public class ThreadDemo02 implements Runnable{
    public static void main(String[] args) {
        //线程的创建
        ThreadDemo02 th = new ThreadDemo02();
        Thread thread = new Thread(th);

        //开启
        thread.start();

        new Thread(new ThreadDemo02()).start();


        for(int i=0;i<=50;i++){
            System.out.println("一边说话...");
        }
    }

    /*
        线程体
     */
    @Override
    public void run() {
        for(int i=0;i<=50;i++){
            System.out.println("一边吃饭...");
        }
    }
}

这里我们可以使用内部类来简化代码

public class ThreadDemo03 {

    //内部类
    static class Inner1 implements Runnable{

        @Override
        public void run() {
            for(int i=0;i<=50;i++){
                System.out.println("一边打游戏...");
            }
        }
    }

    static class Inner2 extends Thread{

        @Override
        public void run() {
            for(int i=0;i<=50;i++){
                System.out.println("一边打上厕所...");
            }
        }
    }

    public static void main(String[] args) {
        //匿名内部类
        new Thread(new Runnable() {
            @Override
            public void run() {
                for(int i=0;i<=50;i++){
                    System.out.println("一边陪女朋友...");
                }
            }
        }).start();

        //lambda
        new Thread(()->{
            for(int i=0;i<=50;i++){
                System.out.println("一边陪直播...");
            }
        }).start();

        //线程开启
        new Thread(new Inner1()).start();

        new Inner2().start();
    }
}

这里我们写一个经典的例子

/*
    龟兔赛跑
        参赛者跑满一百步结束
        乌龟 : 一直跑不休息
        兔子 : 每20步休息2ms
        如果一旦有人赢了游戏就结束
 */
public class ThreadDemo04 {
    public static void main(String[] args) {
        Match match = new Match();

        new Thread(match,"乌龟").start();
        new Thread(match,"兔子").start();
    }
}

//比赛
class Match implements Runnable{
    //结束标识
    private String winner;  //记录赢的人的名字


    @Override
    public void run() {
        //i作为步数
        for(int i=1;i<=100;i++){
            //是否为兔子
            System.out.println(Thread.currentThread().getName()+"正在跑第"+i+"步");
            if("兔子".equals(Thread.currentThread().getName()) && i%20==0){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            //结束判断
            if(checkOver(i)){
                break;
            }
        }

    }

    //结束的条件判定  返回值: true结束   false不结束
    public boolean  checkOver(int steps){
        boolean flag = false;
        //有人赢了
        if(winner != null){
            return true;
        }
        //自己赢了
        if(steps==100){
            winner = Thread.currentThread().getName();
            return true;
        }
        return false;
    }
}

第三种开启线程的方法(了解即可)

Callable 接口 call() ,定义线程体
优点:
可以抛出异常,可以定义返回值

public class ThreadDemo05 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        Match2 match = new Match2();

        //通过线程池 固定大小线程池2个  static ExecutorService newFixedThreadPool(int nThreads)
        //1.创建执行服务
        ExecutorService server = Executors.newFixedThreadPool(2);
        //2.提交任务  <T> Future<T> submit(Callable<T> task) 提交值返回任务以执行并返回表示任务的挂起结果的Future。
        Future<Integer> f1 = server.submit(match);
        Future<Integer> f2 = server.submit(match);

        //3.获取结果
        //Integer result1 = f1.get();
        //Integer result2 = f2.get();

        //System.out.println(result1);
        //System.out.println(result2);

        //4.结束服务
        server.shutdown();

    }
}

//比赛
class Match2 implements Callable<Integer> {
    //结束标识
    private String winner;  //记录赢的人的名字


    /*
        可以抛出异常
     */
    @Override
    public Integer call() throws InterruptedException {
        //i作为步数
        for(int i=1;i<=100;i++){
            //是否为兔子
            System.out.println(Thread.currentThread().getName()+"正在跑第"+i+"步");
            if("兔子".equals(Thread.currentThread().getName()) && i%20==0){
               Thread.sleep(20);
            }
            //结束判断
            if(checkOver(i)){
                return i;
            }
        }
        return null;
    }

    //结束的条件判定  返回值: true结束   false不结束
    public boolean  checkOver(int steps){
        boolean flag = false;
        //有人赢了
        if(winner != null){
            return true;
        }
        //自己赢了
        if(steps==100){
            winner = Thread.currentThread().getName();
            return true;
        }
        return false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值