# API-工具类库 (Package java.util)

# 日期

# Date

基本信息
Package java.util
public class Date

  • 使用Date类对象来表示一个日期。默认创建的对象会获取系统当前时间。

重要方法

格式化日期显示

  • 将字符串转化为日期对象
    使用SimpleDateFormat类向上造型,调用其Date parse(String source)来转换。
    Input

    Date date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2000-02-01 12:42:15");
    
  • 将日期对象转换为字符串 使用SimpleDateFormat类向上造型,调用其StringBuffer format(Date date)来转换。
    Input

    String str = new SimpleDateFormat("yyyy年MM月dd日").format(date);
    

# Calendar

基本信息
Package java.util
public abstract class Calendar

  • 使用静态方法static Calendar getInstance()来获取一个Calendar类实例。

# 集合

# Collcetion接口

基本信息
Package java.util
public interface Collection<E>

  • 是集合类的顶级接口
  • 其中<E>是泛型,代表该集合只能存储E类的数据作为元素(element),且必须是引用数据类型。
    如:Collection<String>限定集合中只能存储String类的数据。

# List接口

基本信息
Package java.util
public interface List<E>

  • 是一种有序的Collection
  • 元素有序(存入顺序),可重复
  • 元素存在下标,可通过下标操作对应的元素

重要实现类
ArrayList

  • 默认初始容量为10;扩容时,在上一次的基础上扩容一半容量
  • 线程不安全的集合
  • 内存空间连续
  • 增删元素比较慢

LinkedList

  • 基于链表实现,增删快,查询慢
  • 线程不安全的集合 LinkedList

Vector

  • Java 中最早的集合,初始容量是10

  • 内存空间连续

  • 每次扩容1倍

  • 线程安全

  • 使用方法elements()来返回枚举

    重要派生类
    Stack

    • 遵循先进后出的原则
    • 最先放入的元素称为栈底元素
    • 最后放入的元素称为栈顶元素
    • 放入——入栈/压栈
    • 拿出——出栈/弹栈

# Queue接口

基本信息
Package java.util
public interface Queue<E>

  • 遵循先进先出的原则。
  • 是一种特殊的Collection
  • 其线性实现有ListQueue

# Set接口

基本信息
Package java.util
public interface Set<E>

  • 是散列的Collection
  • 元素不可重复
  • 不保证存入顺序
  • 基于哈希码存放
  • 若添加相同元素则抛弃
    使用equals()比较时,比较实际元素

重要实现类
HashSet

  • 默认初始容量为 16, 加载因子为 0.75F
    loadFactor 加载因子/装载因子,float类型
  • 每次扩容一倍
  • 是线程不安全的集合

值得注意的是

在数据结构知识中,栈和队列是一种有着特殊规则的线性表。而在 Java 语言中各个集合类之间的继承、实现关系并不完全符合传统数据结构知识。

# 并发

基本信息
Package java.util.concurrent

# BlockingQueue接口

基本信息
public interface BlockingQueue<E>

重要实现类

  1. ArrayBlockingQueue
    是基于数组且有界的阻塞队列。

    重要方法

    1. add(object)

      • 非阻塞
      • 底层调用offer()
      • 添加溢出抛异常IllegalStateException: Queue full
    2. offer(object)

      • 非阻塞
      • 添加溢出返回false
    3. offer(object, timeout, TimeUnit.xxx)

      • timeout期间内一直尝试添加,若超时未添加成功则返回false
    4. put(object)

      • 阻塞
    5. remove(object)

      • 非阻塞
      • 队空,不报错
    6. remove()

      • 非阻塞
      • 队空则抛异常NoSuchElementException
    7. poll()

      • 非阻塞
      • 队空返回null
    8. poll(timeout, TimeUnit.xxx)

      • timeout期间内一直尝试移除队首,若超时未添加成功则返回null
    9. take(object)

      • 阻塞
  2. PriorityBlockingQueue

    • 无界
    • 不允许元素为空
    • 队列中元素对应的类必须实现Comparable接口
      重写compareTo()来进行排序
      • 自然排序,升序
      • 不保证迭代遍历时的顺序
      • 保证逐个取出时的顺序
  3. SynchronousQueue
    只能保存单个元素

# BlockingDeque接口

基本信息
public interface BlockingDeque<E>

  • 双向队列
  • 继承自BlockingQueue

# ConcurrentMap接口

基本信息
public interface ConcurrentMap<K,​V>

重要实现类/接口

  1. ConcurrentHashMap

    • 映射底层依靠键值对存储数据,默认大小为 16
    • 数组的每一个位置维系了一个链表
    • 经过一定位运算分布到 16 个桶中
      当元素碰撞时,两元素键对比;若相同,则覆盖。不同则生成链。
    • 加载因子 0.75f
      避免桶中元素太多影响效率,引入加载因子;
      当达到一定规模,如使用到 个桶以后时,则对桶的数量扩增。之后重新计算全部哈希码,重新排布(Rehash)
  2. ConcurrentNavigableMap接口
    是一种并发导航映射

    重要实现类

    • ConcurrentSkipListMap
      跳跃表

      重要方法

      • headMap(String key)
        从头开始,截取到指定的键之前组成的子map

      • tailMap(String key)
        从尾开始截取

      • subMap(String fromKey, String toKey)
        范围截取

# CountDownLatch

基本信息
public class CountDownLatch

  • 递减锁
  • 在构造时传入,线程执行之后await()
  • 计数线程全部执行完成(进行 countdown 来递减)之后执行await()之后的代码
  • 适合于不同线程进行计数

实例代码

import java.util.concurrent.CountDownLatch;

public class CouuntDownLatchDemo {
   public static void main(String[] args) throws InterruptedException {
      CountDownLatch countDownLatch = new CountDownLatch(2);
      new Thread(new Teacher(countDownLatch)).start();
      new Thread(new Student(countDownLatch)).start();

      countDownLatch.await();

      System.out.println("上课");
   }
}

class Teacher implements Runnable {
   private CountDownLatch countDownLatch;

   public Teacher(CountDownLatch countDownLatch) {
      this.countDownLatch = countDownLatch;
   }

   @Override
   public void run() {
      System.out.println("老师进入教室");
      countDownLatch.countDown();
   }
}

class Student implement Runnable {
   private CountDownLatch countDownLatch;

   public Student(CountDownLatch countDownLatch) {
      this.countDownLatch = countDownLatch;
   }

   @Override
   public void run() {
      System.out.println("学生进入教室");
      countDownLatch.countDown();
   }
}

# CyclicBarrier

基本信息
public class CyclicBarrier

  • 栅栏
  • 在构造时传入,需要阻塞的地方await()
  • await()一次计数减少一次,直到减为 0 放开阻塞
  • 适合于同一线程类产生多个线程计数

实例代码

import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierDemo {
   public static void main(String[] args) {
      CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
      new Thread(new Horse("1"), cyclicBarrier)).start();
      new Thread(new Horse("2"), cyclicBarrier)).start();
      new Thread(new Horse("3"), cyclicBarrier)).start();

      System.out.println("开始比赛");
   }
}

class Horse implements Runnable {
   private String name;
   private CyclicBarrier cyclicBarrier;

   public Horse(String name, CyclicBarrier cyclicBarrier) {
      this.name = name;
      this.cyclicBarrier = cyclicBarrier;
   }

   @Override
   public void run() {
      System.out.println(name + "走到出发点");
      try {
         cyclicBarrier.await();
      } catch (InterruptedException | BrokenBarrierException e) {
         e.printStackTrace();
      }
   }
}

# Exchanger

基本信息
public class Exchanger<V>

  • 交换机
  • 用与交换两个线程的信息

实例代码

import java.util.concurrent.Exchanger;

public class ExchangerDemo {
   public static void main(String[] args) {
      Exchanger<String> exchanger = new Exchanger<>();
      new Thread(new SpyA(exchanger)).start();
      new Thread(new SpyB(exchanger)).start();
   }
}

class SpyA implements Runnable {
   private Exchanger<String> exchanger;

   public SpyA(Exchanger<String> exchanger) {
      this.exchanger = exchanger;
   }

   @Override
   public void run() {
      String msg = "M1";
      try {
         String exchange = exchanger.exchange(msg);
         System.out.println("SpyA 收到 SpyB 的信息:" + exchange);
      } catch (InterruputedException e) {
         e.printStackTrace();
      }
   }
}

class SpyB implements Runnable {
   private Exchanger<String> exchanger;

   public SpyB(Exchanger<String> exchanger) {
      this.exchanger = exchanger;
   }

   @Override
   public void run() {
      String msg = "M2";
      try {
         String exchange = exchanger.exchange(msg);
         System.out.println("SpyB 收到 SpyA 的信息:" + exchange);
      } catch (InterruputedException e) {
         e.printStackTrace();
      }
   }
}

# Semaphore

基本信息
public class Semaphore

  • 信号量
  • 用于限制某段代码在某个时间段内最多只能有规定线程书目进入访问
  • 每个线程进入的时候需要进行acquire()操作,使得信号量-1,知道为0
  • 若有新的线程来访问则会在acquire()操作阻塞,直到之前的某线程release()

实例代码

import java.util.concurrent.Semaphore;

public class SemaphoreDemo {
   public static void main(String[] args) {
      Semaphore semaphore = new Semaphore(5);

      for (int i = 0; i < 10; i++) {
         new Thread(new FileWatching(semaphore)).start();
      }
   }
}

class FileWatching implements Runnable {
   private Semaphore semaphore;

   public FileWatching(Semaphore semaphore) {
      this.semaphore = semaphore;
   }

   @Override
   public void run() {
      String name = Thread.currentThread().getName();
      try {
         semaphore.acquire(); // 信号量 -1
         System.out.println(name + "领取到了眼镜开始观影");
         Thread.sleep(5000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }

      System.out.println(name + "归还眼镜,离开了影院");
      semaphore.release(); // 信号量 +1
   }
}

# ExecutorService接口

基本信息
public interface ExecutorService

  • 类似线程池,实现线程复用
  • 先交由核心线程处理;若核心线程已满则放入工作队列中;若工作队列满则创建临时线程

实例代码

public class ExcutorServiceDemo {
   public static void main(String[] args) {
      // corePoolSize: 核心池大小。线程池中核心线程的数量,创建后不再销毁
      // maximumPoolSize: 允许存在的最大线程数量
      // keepAliveTime:存活时间
      // unit: (存活时间的)单位
      // workQueue: 工作队列,阻塞式队列。在核心线程都被使用的情况下,新请求会被放在工作队列中

      ExecutorService executorService = new ThreadPoolExcutor(5, 10, 3000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue(10));
      for(int i = 0; i < 5; i++) {
         executorService.submit(new Demo()); // 支持Runnable
         // executorService.execute(new Demo()); 支持Callable/Runnable
      }
      executorService.shutdown();
   }
}

class Demo implements Runnable {
   @Override
   public void run() {
      System.out.println(Thread.currentThread().getName() + "被处理");
      try {
         Thread.sleep(3000);
      } catch (InterruptedException e) {
         e.printStackTrace();
      }
   }
}

线程池

Executor提供了三种线程池:CachedThreadPoolFixedThreadPoolForkJoinPool

  • CachedThreadPool

    • 缓存线程池
    • 小队列大池
    • 无核心线程,临时线程存活时间短
    • 能够较好应用高并发场景
    • 不适合长任务场景
    ExecutorService executorService = Executors.newCachedThreadPool();
    
  • FixedThreadPool

    • 大队列小池(传入数目)
    • 所有线程都为核心线程
    • 降低服务器的并发压力
    ExecutorService executorService = Executors.newFiuxedThreadPool(5);
    
  • ForkJoinPool

    • 分叉合并(不推荐使用)

Callable 接口

基本信息
public interface Callable<V>

  • 泛型表示线程执行后的返回值结果
  • Callable只能交给线程池处理

实例代码

class CallableDemo implements Callable<String> {
   @Override
   public String call() {
      for (int i = 0; i < 10; i++) {
         System.out.println(i);
      }
      return "SUCCESS";
   }
}

# 锁与原子操作

    • 类似synchronized机制,但更加灵活
    • 公平策略与非公平策略
      • synchronized为非公平策略

      • Lock接口
        基本信息
        Package java.util.concurrent.locks

        public interface Lock

        具体实现类
        ReentrantLock

        • 默认为非公平策略,可设置为公平策略
        • 通过lock()上锁,unlock()解锁
    • 读写锁ReadWriteLock
      • 使用时允许多个线程同时使用统一资源,但只允许一个线程对资源进行写操作
      • 读期间不允许进行写操作,写期间不允许进行读操作
  • 原子操作 操作时不允许其他操作

# Iterator接口

基本信息
Package java.util
public interface Iterator<E>

Java SE 5.0+
  • 通过指针挪动遍历集合
  • 遍历过程中不允许增删原集合
  • 若一个对象允许使用 foreach 遍历,该类必须实现Iterable接口

# Collections

基本信息
Package java.util
public class Collections

操作集合的工具类

重要方法
compare(T o1, T o2)

  • 返回正负值来确定大小
  • 若为正则第一个数排到第二个数之后;反之排到其前
  • 若没有指定排序规则, 必须实现Comparable接口,比较规则写在compareTo()

# Map接口

基本信息
Package java.util
Interface Map<K,​V>

  • 以键-值对形式存在的数据结构,其中键是唯一的
  • 遍历Map的方法
    • 获取所有键,通过键来获取值
    • 获取键值对组成的集合

重要实现类
HashMap

  • 默认初始容量是 16, 加载因子为 0.75F
  • 每次扩容一倍
  • 允许键或值为null
  • 异步式线程不安全的映射,不对映射做安全限制

HashTable

  • 默认初始容量为 11, 加载因子为 0.75F
  • 不允许键或值为null
  • 同步式线程安全的映射
    • 对外公开的涉及到键值对的操作方法都是同步方法
    • 锁对象是thisHashTable以本身对象作为锁对象

ConcurrentHashMap

  • 异步式线程安全的映射
  • 引入分段锁(分桶锁) 详情见ConcurrentMap

# Properties

基本信息
Package java.util
public class Properties

  • 是一个可以持久化的映射
  • 键和值默认为String类型
  • Properties对象必须存储到properties文件中
  • properties文件中不能存储中文,会变成对应的编码

重要方法
setProperty("键","值")
store(输出流, comments)
load(输入流)

# Scanner

基本信息
Package java.util
public final class Scanner

使用Scanner可以从控制台读取数据。

Scanner sc = new Scanner(System.in);
String name = sc.nextLine();

注意

除了nextLine(),其余都是以空格为结束符