Core Java 卷2 学习笔记

额外

  1. 窗体程序外加EventQueue…invokeLater()的原因:
    awt和swing是单线程模式的, 所有aawt组件只能在事件处理线程中访问, 从而保证组件状态的可确定性

第一章 Java SE8 的流库

1.1 从迭代到流的操作

  1. 流操作的基本使用
    List<String> words = ...
    words.stream.stream().filter(w -> w.length() > 12).count;
    words.parallelStream.stream().filter(w -> w.length() > 12).count; // 并行方式
    
  2. string.split("\\PL+") 将字符串以非字母分割

1.2 流的创建

  1. 数组->流
    Stream<String> words = Stream.of(str); // str是String数组
    Stream<String> words1 = Array.stream(str, 0, 5); // str是String数组
    
  2. 生成无限流
    Stream<String> echos = Stream.generate(() -> "Echo");
    Steam<Double> randoms = Stream.generate(Math::random);
    Stream<BigInteger> integers = Stream.iterate(BigIteger.ZERO, n -> n.add(BigInteger.ONE)); // 产生无限序列流: 0 1 2 3 4
    

1.3 filter、map和flatMap方法

  1. 若使用map会得到包含流的流, 则可以使用flatMap方法将其摊平, 而不是使用Map

1.4 抽取子流和连接流

  1. stream.limit(n)会返回一个新的流, 在n个元素之后结束
  2. stream.skp(n)会丢弃前n个元素
  3. Stream类的静态方法concat(Stream stream1, Stream stream2)可以将两个流连接起来

1.5 其他流转换

  1. stream.distinct()会按顺序剔除重复元素
  2. stream.sorted()可以操作Coparable元素的流或接受一个Comparator
  3. peek方法每次获取一个元素时, 都会调用一个函数

1.6 简单约简

  1. count、max、min、findFirst、findAny、anyMatch、allMatch、noneMatch

1.7 Optional类型

  1. 包装器对象Optional<T>主要函数orElse()orElseGet()orElseThrow()

1.8 收集结果

  1. 流可以调用forEach方法, 将某个函数应用与每个元素, 如stream.forEach(System.out::println);
  2. stream.toArray()返回的是Object[]数组, 如果想让数组具有正确的类型, 应将其传入构造器中stream.toArray(String[]new);
  3. 流的元素收集到List中, 可以使用stream.collect(Collectors.toList());(Set同理)
  4. 流的元素收集到String中, 可以使用stream.collect(Collectors.joining());

1.9 收集到映射表中

  1. Collectors.toMap方法

1.10 群组和分区

  1. 根据函数进行分类
    Map<String, List<Locale>> countryToLocales = locales.collect(Collectors.groupingBy(Locale::getCountry));
    
  2. 当分类函数的返回类型是boolean值是, 分区为两类, 使用partitioningBy比使用groupingBy更高效
    Map<Boolean, List<Locale>> englishAndOtherLocales = locales.collect(
    	Collectors.partitioningBy(l -> l.getLanguage().equals("en")));
    	List<locale> englishLocales = englishAndOtherLocales.get(true);
    
    

1.11 下游收集器

  1. groupingBy可以将各个集组合起来, 但是可能会产生复杂的表达式
  2. 示例:
    cities = readCities("/home/zyq/文档/cities.txt");
    Map<String, Optional<String>> stateToLongestCityName = cities.collect(
            groupingBy(
                    City::getState,
                    mapping(City::getName, maxBy(Comparator.comparing(String::length)))
            )
    );
    System.out.println("stateToLongestCityName: " + stateToLongestCityName);
    

1.12 约简操作

  1. reduce方法是从流中计算某个值的通用机制, 最简单形式接受一个二院函数, 并从前两个元素开始持续应用它. 也可以在将第一个参数设置成计算起点
  2. 复杂示例, 计算字符串流中所有字符穿的长度和, 其中(total, word) -> total + word.length()是累积器, 会被重复调用
    int result = words.reduce(0,
    	(total, word) -> total + word.length(), 
    	(total1, total2) -> total1 + total2);
    

1.13 基本类型流

  1. 创建基本类型流IntStream stream = IntStream.of(..)IntStream stream = Arrays.stream(), 和对象流一样, 可以使用generate和iterate方法
  2. 还可以使用IntStream和LongStream类的静态方法range和rangeClosed生成步长为1的证书范围
  3. 将对象流转换为基本类型流可以使用stream.mapToInt以及stream.mapToLong

1.14 并行流

  1. 不要修改在执行某项流操作后会将元素返回到流中的集合

第二章 输入与输出

2.1 输入/输出流

  1. java中如缓冲和预览等细节需要将多个流过滤器组合起来使用, 提供极大的灵活性
    // 例: 从一个ZIP压缩文件中通过输入流序列来读入数字
    ZipInputStream zin = new ZipInputStream(new FileInputStream("employee.zip"));
    DataInputStream din = new DataInputStream(zin);
    

2.2 文本输入与输出

  1. 文本输出可以使用PrintWriter. 输出可以使用print、println、printf方法. 构造函数第三个参数为Boolean类型, 用于设置是否自动冲刷, 若设置成自动冲刷模式, 那么只要println被调用, 缓冲区中的所有字符都会被发送
    PrintWriter out = new PrintWriter("employee.txt", "UTF-8");
    // 等同于
    PrintWriter out = new PritWriter(new FileOutputStream("employee.txt"), "UTF-8");
    
  2. 文本输入的几种方式
    // 1. Scanner类对象
    // 2. 对短小文本文件
    String content = newString(File.readAllByBytes(path), charset);
    // 3. 逐行读入
    List<String> lines = Files.readAllLines(Path, charset)
    // 4. 文件太大, 将行惰性处理
    try (Stream<String> lines = Files.lines(path, charset)) {
    	......
    }
    

2.3 读写二进制数据

  1. java中所有的值都按照高位在前的模式写出
  2. 写出: 实现了DataOutput接口(writeChars等)的DataOutputStream类; 读入: 实现了DataInput接口(readInt等)的DataInputStream类
  3. 随机访问文件类, RandomAccessFile, 同时实现了DataInput和DataOutput接口, 因此可以使用readInt/writeInt等方法, 使用seek()
    RandomAccessFile in = new RandomAccessFile("employee.dat", "r");
    RandomAccessFile inOut = new RandomAccessFile("employee.dat", "rw");
    

2.4 对象输入/输出流与序列化(疑惑)

  1. 使用的对象需要实现Serializable接口
  2. 对象深克隆的两种方法:
    ①对象类实现Clonable接口, 重写clone()函数
    ②对象类实现Cloneable和Serializable接口, 实现clone()函数, 在函数中将对象序列化到输出流中, 再将其读回, 使用ByteArrayOutputStream将数据保存到字节数组中

2.5 操作文件

  1. Path生成路径后可以使用p.resolve(Path q)p.resolveSibling()p.getParent()等方法对路径进行操作
  2. 小文件的读写使用Files类的静态函数, 大文件或二进制文件使用输入输出流更合适
  3. Files类的静态方法: createDirectory(Path path)createDirectories(Path path)createFile(Path path)
  4. Files类的copy和move函数可以复制和移动文件, delete和deleteIfExists可以删除文件, 使用StandCopyOption的静态变量作为参数可以设置其为原子操作或覆盖原文件等等
  5. 静态的Files.list方法返回可以读取目录中各个项的Stream<Path>对象, 因为是惰性读取, 因此使得处理具有大量项的目录变得高效. Files.list方法不会进入子目录, 为了处理所有子目录, 应该使用Files.walk
  6. 遍历目录中想进行细粒度的控制可以使用Files.newDirectoryStream(dir)方法, 返回一个DirectoryStream<Path>对象. 访问目录的所有子孙成员, 可以调用
    File.walkFileTree(Paths.get(path), new SimpleFileVisitor<Path> {
    	...
    });
    
    同时选择性覆盖其中的操作方法

2.6 内存映射文件(疑惑)

  1. 文件锁是依赖于操作系统的, 同时需要确保在操作完成时释放锁, 因此最好在try中执行
    FileChannel = FileChannel.open(path);
    FileLock lock = channel.lock(); // 无锁时阻塞
    FileLock lock = channel.trylock(); // 无锁时返回null
    
    共享锁: FileLock lock(long position, long size, boolean shared), shared为true则允许多个进程从文件读入

2.7 正则表达式

  1. X+: 1个或多个. X*: 0个或多个. X?: 0个或1个
  2. 正则表达式的使用
    Pattern pattern = Pattern.compile(patternString);
    Matcher matcher = pattern.matcher(input);
    if (matcher.matches())...
    
    编译时可以使用第二个参数设置一个或多个标志
    Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE + Pattern.UNICODE_CASE);
    
  3. 在集合或流中匹配
    Stream<string> result = strings.filter(pattern.asPredictt());
    

第三章 XML

3.1 XML概述

  1. 属性只应该用来修改值的解释, 而不是用来指定值

3.2 解析XML文档

  1. 读入XML文档需要DocumentBuilder对象, 可以从工厂类DocumentBuilderFactory中得到
    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = facetory.newDocumentBuilder();
    File f = ...;
    Document doc = builder.parse(f);
    URL u = ....;
    doc = builder.parse(u);
    
  2. 通过doc.getDocumentElement()方法获得Element元素(根元素). 通过element.getTagName()方法获得元素的标签名. 通过element.getChildNodes()方法获得子元素, 返回NodeList集合, 获得的子元素有可能包含元素标签之间的空白字符
  3. string.trim()方法会把位于实际数据前后的空白字符删掉
  4. element.getFirstChild()获取第一项子元素, element.getNextSibling得到下一个兄弟节点, getLastChild获取最后一项子元素
  5. element.getAttributes()方法返回NamedNodeMap对象, 包含了描述属性的Node对象, 然后调用getNodeNamegetNodeValue方法可以得到属性名和属性值. 如果知道属性名也可以直接使用element.getAttribute(String attrName)方法获得相应属性值

第四章 网络

4.1 连接到服务器

  1. 简单示例
    Socket s = new SOkcet("time-a.nist.gov", 13); // 打开套接字
    InputStream inStream = s.getInputStream();
    
  2. 套接字超时, 超时后会抛出SocketTimeoutException异常
    Socket s = new Socket();
    s.connect(new InetSocketAddress(host, port), timeout);
    
  3. 根据主机名获得主机地址
    InetAddress address = InetAddress.getByName("time-a.nist.gov");
    byte[] addressBytes = address.getAddress();
    // 若一个主机名对应多个主机地址
    InetAddress[] address = InetAddress.getAllByName(host);
    
    // 获取本机地址
    InetAddress address = InetAddress.getLocalHost();
    

4.2 实现服务器

  1. ①开启ServerSocket监听端口②有客户端连接时调用accept返回Socket③利用socket.getInputStream()socket.getOutputStream()获取输入流和输出流
  2. 应采用线程处理类实现Runnable接口, 实现多线程
    while (true) {
    	Socket incoming = s. accept();
    	Runnable r = new ThreadedEchoHandler(incoming);
    
    	Thread t = new Thread(r);
    	t.start();
    }
    
  3. 半关闭, socket.shutdownOutput();关闭输出流, 保持输入流打开
  4. 可中断套接字使用SocketChannel类, 当线程正在执行打开、读取或写入操作时, 如果线程发生终端, 那么这些操作将不会陷入阻塞, 而是以抛出异常的方式结束
    SocketChannel Channel = SocketChannel.open(new InetSocketAddress(host, port));
    Scanner in = new Scanner(channel, "UTF-8");
    OutputStream outStream = Channels.newOutputStream(channel);
    

4.4 获取Web数

  1. URI类可以解析相对URL以及相对化URI
  2. 使用URLConnection获取信息
    URL url = new URL(urlString);
    URLConnection connection = url.openConnection();
    // 获得头字段, 还可以使用connection.getContentType()等
    Map<String, List<String>> headers = connection.getHeaderFields();
    ...
    

第五章 数据库编程

5.3 JDBC配置

  1. 打开数据库连接
    String url = "jdbc:xxxx";
    String username = "xxxx";
    String pasword = "xxxx";
    Connection conn = Drivermanager.getConnection(url, username, password);
    

5.4 使用JDBC语句

  1. INSERT、UPDATE、DELETE、CREATE TABLE、DROP TABLE等操作可以使用executeUpdate方法
    Statement state = conn.createStatement();
    String command = "UPDATE ... SET... WHERE...";
    state.executeUpdate(command);
    
  2. SELECT操作执行executeQuery方法, 返回ResultSet对象
    ResultSet rs = state.executeQuery("SELECT * FROM BOOK");
    while (rs.next()) {
    	...
    }
    

5.5 执行查询操作

  1. 执行操作返回多个结果集时可以使用boolean对象接收执行结果, 如果多结果集下一项是结果集, 将返回true, 如果下一项不是更新计数, 将返回-1

第六章 日期和时间API

6.1 时间线

  1. Instant.now()函数返回当前时刻Instant类对象. Douration.between(Instant start, Instant end)函数返回时间差Duration对象. Duration对象调用toNanostoMillisgetSercondstoMinutestoHourstoDays来获得传统度量单位的时间长度

6.2 本地时间

  1. LocalDate.now()LocalDate.of(int year, int month, int day)返回本地时间类对象
  2. plusDaysplusMonthsminusDaysminusMonthsplusminus(减去Duration或Period)、withDayOfMont(返回新的LocalDate)、getDayOfMonthuntil(获取Period, 或按照给定的ChronoUnit是计算的数值)、isBefore

6.3 日期调整器

  1. TemporalAdjusters接口实现的几个方法, 可以将其返回值传递给LocalDate对象的with函数, 返回一个新的LocalDate对象. 也可以自己实现TemporalAdjuster接口来创建自己的调整器

6.4 本地时间

  1. 存储固定时区的时间点使用LocalDateTime类

6.5 时区时间

  1. 如果计算需跨夏令时或需要处理不同时区的情况, 应该使用ZonedDateTime类
  2. 构造器
    LocalDateTime ldt  = LocalDateTime.of(1990, 12, 30, 2, 30, 0, ZoneId.of("American/New_York"));
    ldt = LocalDateTime.of(LocalDate,of(1990, 12, 30), LocalTime.of(2, 30), ZoneId.of("American.New_York"));
    

6.6 格式化和解析

  1. 使用预定义的格式器
    String formatted = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(apollo1launch);
    
  2. DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
    String formatted = formatter.format(apollo11launch);
    formatted = formatter.withLocale(Locale.FRENCH).format(apollo11launch);
    
  3. 自定义格式
    formatter = DateTImeFormatter.ofPattern("E yyyy-MM-dd HH:mm");
    
  4. 解析
    LocalDate churchsBirthday = LocalDate,parse("1903-06-14");
    ZonedDateTime apollo11launch = ZonedDateTime.parse("1969-07-16 03:32:00-0400", 
    				DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssxx"));
    

第七章 国际化

7.1 Locale对象

  1. 示例
    Locale usEnglish = Locale.forLanguageTag("en-US");
    Locale loc = new Locale("de", "CH");
    loc = Locale.GERMAN;
    

7.2 数字格式

  1. 数字和货币的格式高度依赖于locale
  2. NumberFormat类的静态方法返回相应的数字\货币量\百分比(NumberFormat类对象)格式器, 可以对相应的数据进行格式化解析

7.3 货币

  1. 更改货币格式化器
    NumberFormat euroFormatter = NumberFormat.getCurrencyInstatnce(Locale.US);
    euroFormatter.setCurrency(Currency.getInstance("EUR"));
    

7.4 日期和时间

  1. FormatStyle设置格式化风格
    FormatStyle style = FormatStyle.SHORT; // MEDIUM/LONG/FULL
    DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(style).withLocale(locale)
    

7.5 排序和范化

  1. 因为Collator类实现了Comparator接口, 因此可以将Collator类对象给list.sort(Comparator)方法来进行排序
    Collator coll = Collator.getInstance(locale);
    words.sort(coll);
    
  2. 字符串范化形式存储
    String name = ...;
    String normalized = Normalizer.normalize(name, Normalizer.Form.NFD);
    

7.6 消息格式化

  1. 示例
    String msg = MessageFormat.format("On {2, data, long}, a {0} destroy {1} houses and caused {3, number, currency} of damage.",
    		"hurricane", 99, new GregorianCalendar(1999, 0, 1).getTime(), 10.0E8);
    		)
    
  2. 格式化选项choice
    String pattern = "On {2,date,long}, {0} destroyed {1,choice,0#no houses|1#one house|2#{1} houses}" 
    		+ " and caused {3,number,currency} of demage."
    // no houses |1| one houss |2| {1} houses
    

7.7 文本文件和字符集

  1. 读写文件
    PrintWriter out  = new PrintWriter(filename, "Windows-1252");
    // 获得最佳编码机制
    Charset platformEncoding = Charset.defaultCharset();
    
  2. 针对不同平台行结束符不同
    out.printf("Hello%nWorld%n");
    // Windows上会产生Hello\r\nWorld\r\n
    // 其余平台上会产生Hello\nWorld\n
    
  3. JDK工具native2ascii可以将本地字符编码转换成普通的ASCII, 也可以逆向使用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值