Take you to master: the most complete and detailed Java IO stream

A George 2021-04-16 16:09:26
master complete detailed java io


This paper mainly introduces Java Medium I/O System

If necessary , You can refer to

If help , Don't forget give the thumbs-up *

Preface :

For the designers of programming languages , Create a good input / Output (I/O) The system is a difficult task

Java IO: namely Java Input / Output system . Most programs need to handle some input , And some output is generated by the input , therefore Java For us java.io package

As a qualified program developer , Speaking of IO We are not strangers ,JAVA IO The knowledge system of the system is as follows :

 Take you to master : The most complete and detailed Java IO flow

 

After reading the above picture , Will suddenly , original Java.io There's so much support in the package for us . And we don't have to panic at the same time , It is said that All change is the same , We just need to expand from the source , I believe you can master it well IO Knowledge system .

File class

Read and write operations are inseparable from files (File) Dealing with , So we want to master IO flow , Let's start with the documents .

file (File) The word is not singular Also not The plural , It can represent a special document , It can also represent a set of files in a directory .

list

File If it represents a set of files in a directory , We want to get a catalog of what we can do ?

 Take you to master : The most complete and detailed Java IO flow

 

File It's ready for us  API, According to the return value type , It's not hard to guess that each API The use of methods .

We are known to D There is a TestFile Folder , There are the following files in this folder :

 Take you to master : The most complete and detailed Java IO flow

 

Name list

If we want to get the list of names in the specified directory , We can use these two API:

  • list()
  • list(FilenameFilter filter)
 Take you to master : The most complete and detailed Java IO flow

 

No parameters list() The default method is to list all the file names in the specified directory . If we want to specify a list of directory names, we can use another method :

 Take you to master : The most complete and detailed Java IO flow

 

We expect to have access to test Keyword file name , And it turns out to be what we want .

File list

Sometimes a lot of our operations are not just for a file , It's working on the entire file set . To generate this file set , Then we need the help of File In addition to API The method :

  • listFiles()
  • listFiles(FilenameFilter filter)
  • listFiles(FileFilter filter)

With the above experience , It's not hard for us to guess listFiles() The purpose of this is to list all the files :

 Take you to master : The most complete and detailed Java IO flow

 

In the figure, we've got the file set , This method will also return an array , It's just a File An array of types .

Smart you must have known that if you get a file set with a specified keyword

 Take you to master : The most complete and detailed Java IO flow

 

The same as the file names listed above , That's a smart kid ~

however listFiles(FileFilter filter) What's the difference between the parameters passed by this method and those passed by the above method ? We might as well have a try :

 Take you to master : The most complete and detailed Java IO flow

 

It's also an interface , It also needs to be rewritten accept() Method , But there's only one way File Parameters of . So these two parameters are used for file filtering , The function is the same ~

Catalog tools

Create directory

File Class is not only useful for you to operate on existing directory files , It can also make something out of nothing !

The characteristics of a file are nothing more than : name , size , Last modified date , Can be read / Write , Type, etc

 Take you to master : The most complete and detailed Java IO flow

 

So we go through API And should be able to get :

 Take you to master : The most complete and detailed Java IO flow

 

All of the above types have been obtained , Only one type is missing , Although I say File There is no way to get the type directly , But we can get the full name of the file , Then get the suffix of the file by clipping , You can get the type of the file :

 Take you to master : The most complete and detailed Java IO flow

 

Change hands to operate , Self sufficiency can also get file types , That's a smart kid ~

All of the above operations are based on the existence of file directory , So if the file directory we want to operate on doesn't exist . Or because of our carelessness, we input the name of the file directory wrong , So what's going to happen , Whether the operation process can work normally ?

 Take you to master : The most complete and detailed Java IO flow

 

The result is to throw an exception , It's true that throwing an exception is normal , Isn't it nonsense to operate on a nonexistent file directory

So we can do this when we're not sure the file directory exists :

 Take you to master : The most complete and detailed Java IO flow

 

In the picture we can see two that we haven't seen before API Method , Namely exists() and mkdirs().

  • exists(): Used to verify that the file directory exists
  • mkdirs(): Used to create a directory

Through the above verification before operation , We managed to avoid anomalies . What we need to understand here is , except mkdirs() Can be created outside the directory , One more mkdir() You can also create directories , Except for one of these two methods s outside , There are other differences ?

  • mkdir(): Only one level of directory can be created
  • mkdirs(): You can create multi tier directories
 Take you to master : The most complete and detailed Java IO flow

 

Our current scenario is Test directory does not exist ,dir01 This directory doesn't exist , Then we have to create two levels of directory at this time . But we use mkdir() This method doesn't work , It can't create . So in this case, we should use mkdirs() This method .

File type

File It can be a file or a file set , The file set can contain a file Or a folder , If we want to read and write a file , But inadvertently operated on a folder , That would be awkward , So we can use isDirectory To determine whether it's a folder :

 Take you to master : The most complete and detailed Java IO flow

 

Input and output

We talked about File The basic operation of class , And then we go into I/O modular .

Input and output we often use   flow   The concept , Such as input stream and output stream . It's an abstract concept , Represents any data source object that is related to the ability to produce data or the receiver object that has the ability to receive data . flow It masks the reality I/O The device looks for the details of processing the data !

I/O Can be divided into   Input   and   Output   Two parts .

The input stream is divided into   Byte input stream (InputStream)  and   Character input stream (Reader), Any InputStream or Reader All the derived classes are implemented read() This method , Used to read a single byte or an array of bytes .

The output stream is divided into   Byte output stream (OutputStream)  and   Character output stream (Writer), Any OutputStream or Writer All the derived classes are implemented write() This method , Used to write a single byte or an array of bytes .

So we can see Java The provisions of : All classes related to input should start from  InputStream  Inherit , All classes related to output should start from  OutputStream  Inherit

InputStream

Used to represent classes that generate input from different data sources

What are the different data sources ? Common are :1.  Byte array  2. String object  3.  file  4. “ The Conduit ”( Input... At one end , One end output )

Each of these data sources has a corresponding  InputStream  Subclasses can operate :

class

function

ByteArrayInputStream

Allow buffer of memory to be treated as InputStream Use

StringBufferInputStream

obsolete , take String convert to InputStream

FileInputStream

Used to read information from a file

PipedInputStream

Generate for write correlation PipedOutPutStream The data of , Realization   Pipelining   The concept of

SequenceInputStream

Put two or more InputStream The object is converted to a InputStream

FilterInputStream

abstract class , As an interface to the decorator , For others InputStream Provide useful functions

OutPutStream

This class determines the destination of the output :1.  Byte array  2.  file  3.  The Conduit

common  OutPutStream  Subclasses have :

class

function

ByteArrayOutputStream

Create buffer in memory , All sent to “ flow ” All the data in this buffer

FileOutputStream

Used to write information to a file

PipedOutputStream

Any information written to it will be automatically correlated PipedInputStream Output , Realization   Pipelining   The concept of

FilterOutputStream

abstract class , As a decoration The interface of , For others OutputStream Provide useful functions

Decorator

Through the above understanding , You can see both the input stream and the output stream , There's an abstract class FilterInputStream and FilterOutputStream, These classes are equivalent to a decorator . stay Java in I/O Operation requires a variety of different combinations of functions , And this is the reason to use decorator mode .

What is adornment ? The decorator must have the same interface as the object it decorates , But it can also extend interfaces , It can give us a lot of flexibility , But it also increases the complexity of the code .

FilterInputStream and FilterOutputStream Is used to provide decorator class interfaces to control specific input streams (InputStream) And the output stream (OutputStream) Two classes of .

FilterInputStream

InputStream As a byte input stream , Then the read data should be received by byte array , as follows :

 Take you to master : The most complete and detailed Java IO flow

 

We have to use a byte Array to receive the read value , And then to string type .

Now that we have the decorator FilterInputStream , Can we use the subclass of decorator to help us realize the read operation ? Let's take a look at the common ones FilterInputStream What are the subclasses :

class

function

DataInputStream

And DataOutputStream Use it with , We can read basic data types from streams in a portable way (int,char,long)

BufferedInputStream

Use it to prevent the actual write operation every time you read . representative " buffer "

among DataInputStream It allows us to read data of different basic data types and String object , Match with the corresponding DataOutputStream, We can use data " flow " Move basic types of data from one place to another .

 Take you to master : The most complete and detailed Java IO flow

 

And then it comes to BufferedInputStream Before we look at a set of test code :

 Take you to master : The most complete and detailed Java IO flow

 

There are three text files , among test01.txt It's about the size of  610M,test02/test03 Are empty text files

Now let's use the ordinary InputStream + OutputStream And decorated BufferedInputStream + BufferedOutputStream Write text

Common combination :

 Take you to master : The most complete and detailed Java IO flow

 

Buffer combination :

 Take you to master : The most complete and detailed Java IO flow

 

You can see the difference between the two ways ,4864 ms and 1275 ms. Using a normal combination is equivalent to a buffer of 4 Times as long , If the file is bigger , The difference is amazing ! I'm surprised at the same time , Why is that ?

If you use read() Method to read a file , Access the hard disk once for every byte read , This way of reading is inefficient . Even with read(byte b[]) Method reads multiple bytes at a time , When the file read is large , You also operate on disk frequently .

and BufferedInputStream Of API The document is interpreted as : Creating BufferedInputStream when , An internal buffer array is created . Error reading bytes in stream , The internal buffer can be refilled from the contained input stream as needed , Fill multiple bytes at a time . in other words ,Buffered Class initialization creates a larger byte Array , Read multiple bytes from the underlying input stream at one time to fill byte Array , When a program reads one or more bytes , Directly from byte Get in the array , When in memory byte After reading , The buffer array is filled again with the underlying input stream . So this way of reading data from direct memory is much more efficient than accessing the disk every time .

 Take you to master : The most complete and detailed Java IO flow

 


BufferedInputStream/BufferedOutputStream No direct manipulation of data sources , It's wrapping other byte streams , They are   Processing flow .

The program saves the data to BufferedOutputStream Buffer zone , It wasn't immediately saved to the file , The array in the buffer is saved to the file in the following cases :

  • Buffer full
  • flush() Empty buffer
  • close() Closed flow

FilterOutputStream

OutputStream The basic operation is as follows :

 Take you to master : The most complete and detailed Java IO flow

 

By calling write() Method to write the value to a file , Here are two points to note :

  • The default way to write a document is to override it

As we understand it, call the method twice , The content of the text file should be two lines official account : A small dish is a good memory , But it's actually just one line , This is because the content written later will cover the content that already exists before , The solution is to add append = true

 Take you to master : The most complete and detailed Java IO flow

 

  • The difference between writing and reading is , When reading, if the file does not exist, an error will be reported , But when writing, if the file doesn't exist , It will help you create files by default

OutputStream There are also decorator classes in FilterOutputStream, Here are the common subclasses of decorator class :

class

function

DataOutputStream

And DATAInputStream Use it with , Basic type data can be written to the stream in a portable way (int,char,long etc. )

BufferedOutputStream

Use it to avoid the actual write operation every time data is sent , representative   Use buffer , You can call flush Empty buffer

DataOutputStream and BufferedOutputStream It has been mentioned above , No more details here .

Reader And Writer

stay  Java 1.1  When , On the basic I/O Major changes have been made to the stream class library , Added Reader and Writer Two classes . In my previous limited cognition , You may mistakenly think that these two classes appear to replace InputStream and OutputStream , But the fact is not like my limited cognition .

InputStream and OutputStream It's in byte oriented form for I/O Provide function , and Reader and Writer Is to provide compatibility Unicode In character oriented form I/O Provide function

The two coexist , And provides Adapter  - InputStreamReader and OutputStreamWriter

  • InputStreamReader You can put  InputStream  Convert to  Reader
  • OutputStreamWriter You can put  OutputStream  Convert to  Writer

The two are not exactly the same , But it's also very similar , The contrast is as follows :

Byte stream

Character stream

InputStream

Reader

OutputStream

Writer

FileInputStream

FileReader

FileOutputStream

FileWriter

ByteArrayInputStream

CharArrayReader

ByteArrayOutputStream

CharArrayWriter

PipedInputStream

PipedReader

PipedOutputStream

PipedWriter

Even decoration is almost the same :

Byte stream

Character stream

FilterInputStream

FilterReader

FilterOutputStream

FilterWriter

BufferedInputStream

BufferedReader

BufferedOutputStream

BufferedWriter

PrintStream

PrintWriter

Use Reader  and  Writer  It's also very simple :

 Take you to master : The most complete and detailed Java IO flow

 

Let's take a look at the use of decorators by the way BufferedReader And BufferedWriter

 Take you to master : The most complete and detailed Java IO flow

 

RandomAccessFile

RandomAccessFile  For files consisting of records of known size , So we can use it seek() Transfer records from one place to another , Then read or modify the record . The size of the records in the file is not necessarily the same , As long as we can determine which records are large and where they are in the file .

 Take you to master : The most complete and detailed Java IO flow

 

We can see from the picture that  RandomAccessFile  Not inherited from InputStream and OutputStream Two interfaces , But inherited from some strange DateInput and DataOutput.

It's a bit of a maverick class ~ Let's move on to its constructor :

 Take you to master : The most complete and detailed Java IO flow

 

We've just intercepted part of the constructor , After all, just cut to the point ~

Looking at the constructors, you can see that , There are four patterns defined here :

r

Open text as read-only , Which means you can't use write To manipulate the file

rw

Read and write operations are allowed

rws

Whenever a write operation is performed , Synchronous refresh to disk , Refresh content and metadata

rwd

Whenever a write operation is performed , Synchronous refresh to disk , Refresh content

What's the use ? To put it bluntly RandomAccessFile This class needs everything . Can read , I can write again

essentially ,RandomAccessFile It works in a way similar to  DataInputStream  and  DataOutputStream  Use in combination , Some methods have also been added , One way is getFilePointer() Used to find the current file location ,seek() Used to move to a new location within a file ,length() Used to determine the maximum size of the file . The second parameter is used to show that we are  " random block read (r)"  still  " Read and write (rw)", But it doesn't support separate   Writing documents . Let's actually operate it :

Get read only RandomAccessFile:

 Take you to master : The most complete and detailed Java IO flow

 

Get readable and writable RandomAccessFile

 Take you to master : The most complete and detailed Java IO flow

 

We first wrote... From this file test Four words , Then move the head pointer 3 Write after bit File Four words , The result is testFile, This is because writing begins at the fourth position after moving the pointer .

ZIP

notice zip The word , We should think of compressed files , Yes, the compressed file is Java I/O It's also an extremely important presence in the world . Perhaps it should be said that the compression of files is also extremely important in our development .

stay  Java  Built in classes provide information about ZIP Compressed classes , have access to java.util.zip In bag ZipOutuputStream and ZipInputStream To realize the file's   Compress   and   decompression . Let's take a look at how to compress files first ~

ZipOutputStream

ZipOutputStream  The construction method of is as follows :

public ZipOutputStream(OutputStream out) {/* doSomething */}
Copy code 

We need to pass in one OutputStream object . Therefore, we can generally think that   Compressed files   It's like asking a   Write data to a compressed file , It might sound a little circuitous . Let's take a look first ZipOutputStream Which of them API:

 Take you to master : The most complete and detailed Java IO flow

 

Method

Return value

explain

putNextEntry(ZipEntry e)

void

Start writing a new ZipEntry, And move the position in the stream to this entry The beginning of the value

write(byte[] b, int off, int len)

void

Writes the byte array to the current ZIP Item data

setComment(String command)

void

Set this ZIP The annotation text of the document

finish()

void

Write complete ZIP The content of the output stream , There's no need to turn off what it works with OutputStream

Let's show you how to compress a file :

scene : We need to D Under disk directory TestFile The folder is compressed to D On the plate test.zip in

 Take you to master : The most complete and detailed Java IO flow

 

 Take you to master : The most complete and detailed Java IO flow

 

The specific operation logic is as follows :

 Take you to master : The most complete and detailed Java IO flow

 

Through the above steps, we can compress a file smoothly

ZipInputStream

And how to compress the file , Naturally, how to decompress the file !

public ZipInputStream(InputStream in) {/* doSomethings */}
Copy code 

ZipInputStream  Similar to compressed streams , The constructor also needs to pass in a InputStream object , Beyond all doubt ,API There must be one-to-one correspondence :

 Take you to master : The most complete and detailed Java IO flow

 

Method

Return value

explain

read(byte[] b, int off, int len)

int

Read target b In array off The position of the offset , The length is len byte

avaiable()

int

Judge whether you have finished reading at present entry The specified data , Have read back to 0, Otherwise return to 1

closeEntry()

void

Close the current ZIP Entry and position the stream to read the next entry

skip(long n)

long

Skip the current ZIP The number of bytes specified in the entry

getNextEntry()

ZipEntry

Read next ZipEntry, And move the position in the stream to the entry The beginning of the data in question

createZipEntry(String name)

ZipEntry

With designated name Parameter create a new ZipEntry object

Now let's start with how to unzip a file :

 Take you to master : The most complete and detailed Java IO flow

 

Don't be scared by the length of the code , If you read it carefully, it's easy to unzip the file :

We go through getNextEntry() Method to get a ZipEntry, The way to get the file here is similar to depth traversal , The directory returned each time is roughly as follows :

 Take you to master : The most complete and detailed Java IO flow

 

Every time will traverse all the files in a directory , for example dir01 All the files under the folder , Will continue to traverse dir02 Folder , So we don't have to use recursion to get all the files . After getting every file , adopt ZipFile Get the output stream , Then write it to the unzipped file . The general flow is as follows :

 Take you to master : The most complete and detailed Java IO flow

 

new I/O

JDK1.4 Of java.nio.* A new  JavaI/O  Class library , The purpose is simple , It's about speed . actually , old I/O The package has been used nio It has been realized again , In order to make full use of this speed to improve .

As long as the structure used is closer to the operating system execution I/O The way , Then the speed will naturally increase , So there are two concepts : passageway and Buffer .

How do we understand   passageway   and   Buffer   Two concepts . We can think of the buffer as a small train in a coal mine , The passage is the track of a train , A small train carrying a full load of coal from the mine to other places . So we don't interact directly with the channel , But interact with the buffer , And send the buffer to the channel . The channel either gets the data from the buffer , Or send data to buffer .

ByteBuffer Is the only buffer that directly interacts with the channel , Buffer that can store raw bytes .

ByteBuffer buffer = ByteBuffer.allocate(1024);
 Copy code 

ByteBuffer You can usually create it through allocate() Method to create . meanwhile ByteBuffer Chinese support  4  Created in  ByteBuffer

 Take you to master : The most complete and detailed Java IO flow

 

For better support   new I/O , used I/O  Three classes in the class library have been modified , To produce FileChannel. The modified classes are :FileInputStream,FileOutputStream And for both reading and writing RandomAccessFile. It's worth noting here that these are byte operation streams , Because character streams cannot be used to generate channels , however Channels Practical methods are provided in , Used to generate... In a channel  Reader  and  Writer

Get access to

As we've learned above, there are three classes that support generation channels , The specific method of generating channel is as follows :

 Take you to master : The most complete and detailed Java IO flow

 

These are the three ways to create channels , And read and write operation test . Let's take a look at the test code in the figure below , Then sum up :

  • getChannel() The method will produce a FileChannel. We can send it something that can be read and written ByteBuffer. We store bytes in ByteBuffer One way to do this is : Use put() Method to fill them directly , Fill in one or more bytes , Or the value of the basic data type . however , You can also use wray() Method will have an existing byte array  " packing "  To ByteBuffer in . So you don't have to copy the underlying array , But as a result of it  ByteBuffer  The memory of , It can be called   Arrays support ByteBuffer
  • We can still see that FileChannel Used position() Method , This method can be moved anywhere in the file FileChannel, ad locum , We move it to the end , And then do other read and write operations .
  • For read-only access , We have to explicitly use static allocate() Method to allocate ByteBuffer. If we want to get better speed, we can also use allocateDirect() , In order to produce a system with higher coupling with the operating system  " direct "  Buffer . But the cost of this allocation will be greater , And the specific implementation varies with the operating system .
  • If we want to call read() Come to ByteBuffer Store bytes , You have to call... On the buffer flip() Method , This is to tell FileChannel , Get it ready for someone else to read bytes , Of course , It's also for maximum speed . Here we use  ByteBuffer  After receiving the byte, it does not continue to use the buffer for further operation , If you need to continue read() Words , We have to call clear() Methods for each read() How to prepare .

The channels are connected

Programmers are often lazy , The above one reads and then notifies FileChannel There seems to be a bit of trouble with the way . So is there a simpler way ? There must be , Or I wouldn't ask, would I ~ That is to connect one channel directly to another , It's going to take a special approach transferTo() and transferFrom() . The specific use is as follows :

 Take you to master : The most complete and detailed Java IO flow

 

With the help of Method 1  or   Method 2  Can successfully write the file to test03.txt In file

END

I/O Operation is an indispensable knowledge in our daily development , So we have to master this one !

 Take you to master : The most complete and detailed Java IO flow

 

Link to the original text :
https://juejin.cn/post/6937136570113720327

Last , Xiaobian has also prepared an interview dictionary for you , Add assistant if necessary vx:mxzFAFAFA To collect !!
 
版权声明
本文为[A George]所创,转载请带上原文链接,感谢
https://javamana.com/2021/04/20210416144155778Y.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云