您的浏览器不支持JavaScript,请开启后继续
Java编程问题

Java编程问题

  • 作者
  • (罗)安赫尔·伦纳德(Anghel Leonard) 著

本书通过探讨Java开发工作中常会遇到的问题及相关解决方案,介绍了涉及字符串、数字、数组、集合、数据结构、日期和时间、对象、不可变性、Switch表达式、类型推断、Java I/O、Java反射、函数式编程、并发、HTTP Client API和Websocket等方面的核心知识与实用技巧。 这些简单或复杂的问题,将帮助你提升解决现实问题的编程能力,使你了解相关问题基于Java 8...


  • ¥149.00

ISBN: 978-7-122-44959-7

版次: 1

出版时间: 2024-07-01

图书信息

ISBN:978-7-122-44959-7

语种:汉文

开本:16

出版时间:2024-07-01

装帧:平

页数:566

内容简介

本书通过探讨Java开发工作中常会遇到的问题及相关解决方案,介绍了涉及字符串、数字、数组、集合、数据结构、日期和时间、对象、不可变性、Switch表达式、类型推断、Java I/O、Java反射、函数式编程、并发、HTTP Client API和Websocket等方面的核心知识与实用技巧。
这些简单或复杂的问题,将帮助你提升解决现实问题的编程能力,使你了解相关问题基于Java 8~12的最佳实践,同时还可以检测你对相关技术的掌握程度。
本书可供初级和中级Java开发人员参考,同样也适合正为相关技术面试做准备的求职者阅读。

编辑推荐

JDK8-21版本快速迭代,即使仅关注LTS版,层出不穷的新特性也会令开发人员应接不暇。尤其是国内众多项目仍是基于JDK8、JDK11、JDK17开发的,所以本书并不总是提倡新的解决方案,而是侧重于主流版本JDK8和JDK11来呈现某个问题的合理解决方案。 本书精心挑选269个Java开发人员日常开发中经常需面对的难题,涉及字符串、数字、集合、数据结构、日期和时间、不可变性、类型推断Optional、Java I/O、Java反射、函数式编程、并发和HTTP Client和WebSocket等内容。 书中为这些问题提供了解决思路与方案,这些宝贵的经验不仅能帮你实现更优雅的解决方案,也有助于你更从容地面对Java面试与笔试。

图书前言

JDK 8到12的版本快速迭代,使得现代Java的学习曲线变得陡峭,也增加了开发人员进入熟练编码期的时间成本。然而,这些新的特性和概念,可以用来解决当下的许多问题。本书将从复杂性、性能、可读性等方面入手,通过解释正确的实践和决策,让你能够采用客观的方法来解决常见问题。
本书涵盖了很多主题,如字符串、数字、数组、集合、数据结构、日期和时间、不可变性、类型推断、Optional、Java I/O、Java反射、函数式编程、并发和HTTP client API等,共包含1000+示例和300+应用程序。通过学习这些内容,你可以提高编程水平,丰富技能工具箱,顺利完成各种日常任务。无论你的任务简单、中等还是复杂,掌握这些核心知识都是必要的。
阅读本书后,你将深刻理解很多Java的概念,并能够在面对开发问题时,设计出最佳的解决方案。
本书适合谁
本书对于初学者和中级Java开发人员特别有用。同样的,书中深入探讨的问题也是大部分Java开发者在日常工作中可能会遇到的难题。
阅读本书并不需要过多的技术背景,只需你热爱Java,并且具备阅读Java代码片段的能力。
本书包含了什么内容
第1章,字符串、数字和数学,我们将探讨39个涉及字符串、数字和数学运算的问题。首先,我们会研究一些经典的字符串问题,如统计重复项数量、反转字符串以及删除空格等。随后,我们会深入探讨数字和数学运算相关问题,例如计算大数之和、处理运算溢出、比较无符号数,以及计算取整除和模数等。在解决这些问题时,我们不仅会提供多种方法,还将尝试运用Java 8的函数式编程风格。此外,我们还会讨论一些与JDK 9、10、11和12版本相关的话题。
第2章,对象、不可变性和Switch表达式,包含18个涉及对象、不可变性和Switch表达式的问题。本章从几个处理空引用的问题开始,然后探讨检查索引、equals()和hashCode()以及不可变性(例如,编写不可变类,并在不可变类中传递/返回可变对象)。本章的最后一部分涉及克隆对象和JDK 12的新版Switch表达式。到本章结束时,你将基本了解对象和不可变性。此外,你还将知道如何处理新版的Switch表达式。这些知识对于任何Java开发人员来说都是宝贵且必不可少的。
第3章,处理日期和时间,我们将探讨20个与日期和时间相关的问题,包括转换、格式化、加减、定义周期/持续时间、计算等方面。在此过程中,我们会用到Date、Calendar、LocalDate、LocalTime、LocalDateTime、ZonedDateTime、OffsetDateTime、OffsetTime和Instant等类。通过本章的学习,你将能够熟练掌握各种日期和时间操作,了解相关API,并能将这些知识整合应用到实际业务需求中。
第4章,类型推断,包含21个涉及JEP 286或Java局部变量类型推断(LVTI)的问题,也称为var类型。这些问题经过精心设计,以揭示使用var的最佳实践和常见错误。到本章结束时,你将全面了解var,以便在生产环境中应用它。
第5章,数组、集合和数据结构,我们将详细讨论与数组、集合和数据结构相关的30个问题,并提供其解决方案。这些问题涵盖了众多常见需求,如排序、检索、比较、反转、填充、合并、复制及替换等操作。所有的解决方案都是基于Java 8~12版本实现的。读完本章后,你将构建起一套完善的知识体系,以便更有效地解决各类与数组、集合和数据结构有关的问题。
第6章,Java I/O路径、文件、缓存、扫描和格式化,包括20个Java文件I/O相关的问题。通过操作、轮询、监听文件流路径,以及介绍读写文本文件/二进制文件的有效方式,本章将涵盖Java开发者日常可能遇到的绝大多数I/O相关问题。这些知识将为你解决相关问题提供思路。
第7章,Java反射类、接口、构造函数、方法和字段,包括17个Java反射API的相关问题,从那些经典问题,如检查和实例化Java artifact(模块、包、类、接口、超类、构造函数、方法、注解、数组等),到JDK 11引入的合成构造函数和基于嵌套的访问控制,据此提供了对Java反射API的全面介绍。看完本章后,Java反射API在你面前将再无任何秘密,你可以给你的同事秀下反射都可以做什么。
第8章,函数式编程:基础与设计模式,包括11个和Java函数式编程相关的问题。首先我们将从零开始了解生成函数式接口的完整过程,然后还将使用函数式编程来解释一套基于GoF的设计模式。
第9章,函数式编程:进阶,包括22个Java函数式编程的进阶问题。在本章我们会重点关注流的经典操作(如f?ilter和map)的相关问题,并讨论无限流、null-safe流和默认方法这些内容。本章还会涵盖分组、分区、收集器(包括JDK 12的teeing()收集器和自定义收集器开发)这些内容。此外,我们也会针对takeWhile()、dropWhile()、组合函数、谓词、比较器、Lambda表达式的验证和调试等其他热门问题展开讨论。
第10章,并发:线程池、Callable接口以及同步器,包含了涉及Java并发的14个问题。我们从几个涉及线程生命周期、对象和类级别的锁的基础问题开始,然后讨论关于Java线程池的一系列问题,包含JDK 8实现的工作窃取(work-stealing)线程池。之后,我们会花点精力研究Callable和Future。最后,我们将探究Java有关同步器的一些问题【例如屏障(barrier)、信号量(semaphore)和交换器(exchanger)】。通过本章的学习,你应该可以熟悉Java并发的主要内容并准备好处理一些高级问题了。
第11章,并发:深入探讨,包含13个Java并发相关问题,涵盖fork/join框架、CompletableFuture、ReentrantLock、ReentrantReadWriteLock、StampedLock、原子变量(atomic variables)、任务取消、可中断方法、thread-local和死锁(deadlock)等内容。并发性是每一位开发人员的必修课,尤其在求职面试中颇受重视,这也是为什么上一章和本章如此重要的原因。完成本章阅读后,你将对并发有相当的了解
第12章,Optional,包括24个问题,旨在提示你注意使用Optional的几条规则。
第13章,HTTP Client和WebSocket API,包括20个涵盖HTTP Client和WebSocket API的相关问题。还记得HttpUrlConnection吗?JDK 11附带的HTTP Client API可以认为是对HttpUrlConnection的重新发明。HTTP Client API易于使用并支持HTTP/2(默认)和HTTP/1.1。为了向后兼容,当服务器不支持HTTP/2时,HTTP Client API会自动从HTTP/2降级到HTTP 1.1。此外,HTTP Client API支持同步和异步编程模型,并依赖流来传输数据(响应式流)。它还支持WebSocket协议,该协议在实时Web应用程序中被使用,以提供具有低开销的客户端-服务器通信。
如何从本书中获得最大的收益
最好先掌握一些Java语言的基础知识,建议安装以下组件:
· 适合自己的IDE(非必须)。
· JDK 12和Maven 3.3.x。
· 必要时,安装一些额外的第三方库。
下载示例代码文件
你可以从https://***。
以下是下载代码文件的详细步骤:
1.在https://***。
2.选择支持(Support)选项卡。
3.点击代码下载(Code Downloads)。
4.在搜索(Search)框中输入书名,然后按照屏幕上的指示进行操作。
下载文件后,请务必使用最新版本的软件进行解压:
· 适用于Windows的WinRAR / 7-Zip。
· 适用于Mac的Zipeg / iZip / UnRarX。
· 适用于Linux的7-Zip / PeaZip。
本书的代码包也托管在GitHub上,其网址为https://***
此外,Packt还提供了更多书籍资源,你可以在https://***
下载彩色图像
本书还提供了书中所涉及图片的PDF文件(彩色图像)。你可以在这里下载:https://static.packt-***
书中的特殊文本格式说明
CodeInText:表示文本中的代码字、数据库表名称、文件夹名称、文件名、文件扩展名、路径名、虚拟URL、用户输入和Twitter句柄等。例如:“如果当前字符存在于Map实例中,那么只需将其出现次数加1。”
书中代码格式如下:
public Map countDuplicateCharacters(String str) {
 Map result = new HashMap<>();
 //或者使用for (char ch : str.toCharArray()) { ... }
 for (int i = 0; i < str.length(); i++) {
  char ch = str.charAt(i);
  ***pute(ch, (k, v) -> (v == null) ? 1 : ++v);
 }
 return result;
}
粗体:用于表示新的术语、重要的文本等。例如,菜单或对话框中出现的词语,在文本中呈现如下:“在Java中,逻辑AND运算符用&&表示,逻辑OR运算符用||表示,逻辑XOR运算符用^表示。”
提示:提示和技巧以这种形式呈现。



译者的话
关于本书
这是一本Java领域的重量级作品。尽管本书首版出版于2019年末,但时至今日,书中围绕JDK 8~12的特性所展开的探索与实践,仍然值得众多开发者深入学习体会。
本书的特色在于,它不仅会告诉你该如何运用好Java这门语言,还会剖析一些常见的编程陷阱,帮助你规避一些开发问题,从而编写出更加高效和优雅的程序。所以,无论是从头到尾详读各章内容并主动实践,还是从感兴趣的章节或具体问题入手,你一定会从这200多个精心设计的问题中获得宝贵的经验。
关于我们
我们很荣幸能够负责本书的翻译工作。在翻译分工方面,金嘉怡负责前后辅文及第1~5章,夏钰辉负责第6~9章,黄坚负责第10~13章。在大家完成翻译之后,金嘉怡负责通读全文,完成校对与统稿,并尽量保证风格和术语的统一。
形成初稿后,为了让不同读者群体都有良好的阅读体验,金嘉怡还邀请到了数十位审校成员,其中不乏多位具有8年、5年、3年以上工作经验的开发者,以及刚毕业的计算机专业的朋友。大家的奉献使得本书更趋完善,其中,经验丰富的从业者为内容的专业性提供了保障,而新手视角的建议,也让各种复杂概念的表述更加通俗易懂。
参与审校的贡献者分别是郭泽轩、韩西雅、侯旭、蓝海珊、李琦敏、李永敬、刘琼、龙翔、陆双双、沈曼、石一舟、谭文斌、王铭洋、王胜、王思未、王晓迪、魏黎、邢立文、熊梓潼、徐增昀、杨茜岚、易玉、赵晓晖、周银、朱子晟(按照姓名拼音排序)等。在此,诚挚感谢为本书无私付出的每一位贡献者。
本书的翻译工作历时近一年,大家都牺牲了大量的个人时间,尽管我们已经尽最大努力来给读者呈现最好的效果,但由于水平有限,译作中仍不可避免地存在一些疏漏及不足之处。期待大家提出宝贵的意见,帮助我们不断改进。

金嘉怡 夏钰辉 黄坚
2023年12月 

目录

第1章 字符串、数字和数学	1
问题	1
解决方案	2
1.统计重复字符的数量	3
2.寻找第一个非重复字符	5
3.反转字母和单词	7
4.检查字符串是否仅包含数字	7
5.统计元音和辅音的数量	8
6.统计某个特定字符的出现次数	10
7.将String转换为int、long、float或double类型	11
8.去除字符串中的空格	12
9.用分隔符连接多个字符串	12
10.生成全部排列组合	13
11.检查字符串是否为回文	15
12.删除重复的字符	16
13.删除给定的字符	17
14.找到出现次数最多的字符	19
15.按长度对字符串数组排序	20
16.检查字符串是否包含子串	22
17.计算字符串中子串的出现次数	22
18.判断两个字符串是否互为变位词	23
19.声明多行字符串(文本块)	24
20.重复拼接同一个字符串n次	25
21.删除首尾空格	27
22.寻找最长公共前缀	27
23.应用缩进	28
24.字符串转换	30
25.求最小值与最大值	30
26.求两个大数之和(int/long)并处理运算溢出的情况	31
27.解析特定进制下的无符号数	32
28.通过无符号转换转变数字	33
29.比较两个无符号数	33
30.无符号数的除法和取模	34
31.判断float/double是否为有限浮点数	34
32.对两个布尔表达式执行逻辑AND / OR / XOR运算	35
33.将BigInteger转换为基本类型	36
34.将long类型转换为int类型	37
35.计算取整除和模数	37
36.相邻浮点数	38
37.求两个大数的乘积(int/long)并处理运算溢出的情况	39
38.融合乘加(FMA)	40
39.紧凑数字格式化	41
小结	44

第2章 对象、不可变性和Switch表达式	45
问题	45
解决方案	46
40.用函数式和命令式风格的代码检查空引用	46
41.检查空引用并抛出自定义的NullPointerException异常	48
42.检查空引用并抛出指定的异常	50
43.检查空引用并返回非空默认引用	51
44.检查索引是否在【0, length)范围内	52
45.检查子区间是否在【0, length)范围内	54
46. equals()和hashCode()	55
47.简述不可变对象	59
48.不可变字符串	59
49.编写一个不可变类	62
50.在不可变类中传递/返回可变对象	63
51.使用建造者模式编写不可变类	65
52.避免在不可变对象中出现错误数据	68
53.克隆对象	69
54.重写toString()	73
55.新版Switch表达式	75
56.多个case标签	77
57.语句块	77
小结	78

第3章 处理日期和时间	79
问题	79
解决方案	80
58.字符串与日期时间的转换	80
59.格式化日期和时间	83
60.获取当前日期/时间(不含时间/日期)	86
61.基于LocalDate和LocalTime构建LocalDateTime	86
62.通过Instant类获取机器时间	86
63.使用基于日期的值(Period)定义时间段;使用基于时间的值(Duration)表示一小段时间	89
64.提取日期和时间单位	93
65.加减日期时间	94
66.获取所有时区的UTC和GMT	95
67.获取所有可用时区的本地日期时间	96
68.显示有关航班的日期时间信息	97
69.将Unix时间戳转换为日期时间	99
70.查找某月的第一天/最后一天	99
71.定义/提取时区偏移	102
72.在Date和Temporal之间转换	103
73.遍历一段日期范围	106
74.计算年龄	108
75.获得一天的起始和结束时间	108
76.两个日期之间的差异	111
77.实现一个国际象棋计时器	113
小结	116

第4章 类型推断	117
问题	117
解决方案	118
78.简单的var示例	118
79.使用var与基本类型	120
80.使用var和隐式类型转换来提高代码的可维护性	121
81.显式向下转型(downcast)应避免使用var	122
82.在变量名没有足够的类型信息保障可读性时应避免使用var	123
83.结合LVTI和面向接口编程技术	124
84.结合LVTI和钻石操作符	124
85.将数组赋值给var	125
86.在多变量声明中使用LVTI	126
87. LVTI和变量作用域	127
88. LVTI和三元操作符	128
89. LVTI和for循环	129
90. LVTI和流	130
91.使用LVTI拆分嵌套/大型表达式链	130
92. LVTI和方法返回值及参数类型	131
93. LVTI和匿名类	132
94. LVTI可以是final变量或effectively final变量	132
95. LVTI和Lambda表达式	134
96. LVTI和空初始化器、实例变量以及catch块变量	134
97. LVTI和泛型类型	135
98. LVTI、通配符、协变和逆变	136
小结	138

第5章 数组、集合和数据结构	139
问题	139
解决方案	140
99.对数组进行排序	140
100.查找数组元素	149
101.检查两个数组是否相等或不匹配	153
102.按字典序比较两个数组	156
103.用数组创建流	158
104.计算数组的最小值、最大值和平均值	159
105.反转数组	162
106.填充和设置数组	164
107.下一个更大的元素(NGE)	165
108.改变数组大小	166
109.创建不可修改/不可变的集合	167
110.映射默认值	172
111.判断Map中键是否存在或缺失	173
112.从Map中移除元素	177
113.替换Map条目	178
114.比较两个Map 	179
115.对Map进行排序	180
116.复制HashMap	182
117.合并两个Map 	183
118.移除集合中所有符合谓词条件的元素	184
119.将集合转换为数组	186
120.使用列表筛选集合	187
121.替换列表元素	188
122.线程安全的集合、栈和队列	189
123.广度优先搜索(BFS)	193
124.前缀树(Trie)	195
125.元组(Tuple)	198
126.并查集	200
127.芬威克树或二进制索引树	203
128.布隆过滤器	206
小结	209

第6章 Java I/O路径、文件、缓存、扫描和格式化	210
问题	210
解决方案	211
129.创建文件路径	211
130.变换文件路径	214
131.拼接文件路径	215
132.通过两个路径创建相对路径	216
133.比较文件路径	217
134.轮询路径	218
135.监听路径	225
136.流式获取文件文本内容	228
137.在文件树中搜索文件或文件夹	228
138.高效读写文本文件	230
139.高效读写二进制文件	235
140.大文件搜索	239
141.将一个JSON/CSV文件作为一个对象读取	241
142.处理临时文件和文件夹	245
143.过滤文件	249
144.判断两个文件是否不匹配	252
145.循环字节缓冲区	254
146.标记解析文件	259
147.将格式化输出直接写入文件	263
148.使用Scanner	265
小结	268

第7章 Java反射类、接口、构造函数、方法和字段	269
问题	269
解决方案	270
149.检查包	270
150.检查类和超类	273
151.通过反射构造函数实例化	279
152.获取参数上的注解	282
153.获取合成构造函数	283
154.检查可变参数	284
155.检查默认方法	285
156.通过反射实现基于嵌套的访问控制	285
157.面向getter和setter使用反射	288
158.反射与注解	294
159.调用实例方法	299
160.获取静态方法	300
161.获取方法、字段和异常的泛型	301
162.获取公共字段和私有字段	304
163.处理数组	305
164.检查模块	306
165.动态代理	307
小结	310

第8章 函数式编程:基础与设计模式	311
问题	311
解决方案	311
166.编写函数式接口	312
167. Lambda简介	317
168.实现环绕执行模式	318
169.实现工厂模式	320
170.实现策略模式	322
171.实现模板方法模式	323
172.实现观察者模式	325
173.实现贷出模式	327
174.实现装饰器模式	329
175.实现级联建造者模式	332
176.实现命令模式	333
小结	335

第9章 函数式编程:进阶	336
问题	336
解决方案	337
177.测试高阶函数	337
178.测试使用Lambda表达式的方法	338
179.调试Lambda表达式	340
180.过滤流中的非0元素	342
181.无限流、takeWhile()和dropWhile()	344
182.映射流中的元素	351
183.找出流中的元素	356
184.匹配流中元素	357
185.流中的sum、max和min操作	359
186.收集流的返回结果	362
187.连接流的返回结果	364
188.聚合收集器	365
189.分组(grouping)	369
190.分区(partitioning)	376
191. filtering、flattening和mapping收集器	379
192. teeing	382
193.编写自定义收集器	385
194.方法引用	389
195.并行处理流	391
196. null-safe流	395
197.组合方法、谓词和比较器	397
198.默认方法	402
小结	403

第10章 并发:线程池、Callable接口以及同步器	404
问题	404
解决方案	405
199.线程生命周期状态	405
200.对象级锁与类级锁的对比	410
201. Java中的线程池	413
202.单线程的线程池	417
203.拥有固定线程数量的线程池	423
204.带缓存和调度的线程池	424
205.工作窃取(work-stealing)线程池	430
206. Callable和Future	435
207.调用多个Callable任务	440
208.锁存器(latch)	442
209.屏障(barrier)	445
210.交换器(exchanger)	448
211.信号量(semaphore)	451
212.移相器(phaser)	453
小结	458

第11章 并发:深入探讨	459
问题	459
解决方案	460
213.可中断方法	460
214. fork/join框架	463
215. fork/join框架和compareAndSetForkJoinTaskTag()	469
216. CompletableFuture	472
217.组合多个CompletableFuture实例	486
218.优化忙等待	490
219.任务的取消	491
220.线程局部存储(ThreadLocal)	492
221.原子变量	496
222.可重入锁(ReentrantLock)	500
223.可重入读写锁(ReentrantReadWriteLock)	503
224.邮戳锁(StampedLock)	505
225.死锁(哲学家就餐问题)	508
小结	511

第12章 Optional	512
问题	512
解决方案	513
226.初始化Optional	513
227. Optional.get()和值丢失	514
228.返回一个预先构造的默认值	514
229.返回一个不存在的默认值	515
230.抛出NoSuchElementException异常	516
231. Optional和null引用	517
232.消费一个存在内容的Optional类	518
233.根据情况返回一个给定的Optional类(或另一个Optional类)	519
234.通过orElseFoo()链接多个Lambda表达式	519
235.不要只是为了获取一个值而使用Optional	521
236.不要将Optional用于字段	521
237.不要将Optional用于构造函数的参数	522
238.不要将Optional用于setter类方法的参数	523
239.不要将Optional用于方法的参数	524
240.不要将Optional用于返回空的或者null的集合或数组	526
241.避免在集合中使用Optional	527
242.将of()和ofNullable()搞混淆	528
243. Optional与OptionalInt	529
244.确定Optional的相等性	529
245.通过map()和flatMap()转换值	530
246.通过Optional.filter()过滤值	532
247.链接Optional和Stream API	532
248. Optional和识别敏感类操作	534
249.在Optional的内容为空时返回布尔值	535
小结	535

第13章 HTTP Client和WebSocket API	536
问题	536
解决方案	537
250. HTTP/2	537
251.触发一次异步GET请求	538
252.设置一个代理	540
253.设置/获取请求头	540
254.指定HTTP方式	542
255.设置请求体	543
256.设置连接身份认证	545
257.设置请求超时	546
258.设置重定向策略	546
259.发送同步和异步请求	547
260.处理cookie	549
261.获取响应信息	550
262.处理响应的请求体类型	550
263.获取、更新和保存JSON	552
264.压缩	555
265.处理表单数据	556
266.下载资源	557
267.使用multipart上传	558
268. HTTP/2的服务器端推送	561
269. WebSocket	564
小结	566

发送电子邮件联系我们