- 博客(78)
- 收藏
- 关注
原创 数据结构——栈与队列
Java中的栈和队列都归属于Java集合类,它们是顺序表、链表概念的延申,其中栈在集合框架中作为一个实体类存在,也就是说可以直接通过new Stack来使用,而队列在集合框架中是一个接口,使用的时候必须要依靠实现了Queue接口的类来使用,比如LinkedList。下面就具体介绍以下栈和队列各自的特性以及如何自己实现它们。一、栈栈的特性主要就是后进先出,可以想象成把书本放入箱子里面,当我们需要取最下面的一本书的时候,肯定得先把后面放进去的处于顶上的书本取出来。栈仅仅只支持三个操作,分别是入栈出栈
2021-10-12 23:52:49
239
原创 理解Java中的反射机制
反射是面向对象程序设计中的一种重要特性,它的作用在于可以在程序运行的时候动态的获取到某个类/对象的详细信息,包括但不限于类包含了哪些属性、属性的名字等等。正常来讲,这些信息应该是在写代码的时候通过读源代码获取到的,程序编译成字节码之后,这些信息就丢失了。但是在Java中,这些信息被保留在了字节码文件中,并且会在运行的时候组织成类对象保存在JVM的方法区中,利用反射机制就可以获取到这个类对象,进而获取到该类的详细信息并且可以通过这个类对象实例化出该类的对象。class Animal{ private
2021-10-11 15:15:33
268
原创 抽象类和接口的注意点
一、抽象类:抽象类不能被实例化,也就是不能被"new"。虽然不能被实例化,但是可以在这个类里面定义一些普通类一样的方法或者属性,可以被子类继承过去使用。如果一个类继承了抽象类,那么这个类就必须重写抽象类中的抽象方法。抽象类或者抽象方法一定不能被final关键字所修饰,否则的话就无法被继承或者重写。虽然不能被实例化,但是仍然可以发生向上转型,也就是以抽象类类型的引用去指向它的子类的实例。抽象类和抽象方法一般用abstract关键字修饰。二、接口接口是抽象类的更进一步,抽象类中还可以包含普通
2021-10-10 22:56:32
251
原创 Java中四个访问修饰限定符的用法
Java中一共有四个访问修饰限定符,用于修饰方法或者属性,它们分别是public、protected、default、privatepublicpublic修饰符的访问级别最高,换句话说也就是最不严格,不管在哪个地方都能访问。protectedprotected修饰符主要用于互为继承关系的类中,当父类中的属性或者方法用protected修饰符修饰的时候,就只会允许它的子类进行访问。defaultdefault关键字也叫作包访问修饰符,作用就是主要在同一个包底下的类,互相之间就可以进行
2021-10-10 22:34:53
752
原创 this和super关键字的用法
一、this关键字的用法this关键字代表当前对象的引用,用在当前类中。主要有三个用法this(),代表在当前类中调用其他的构造方法,并且只能在构造方法中写,只能调用一次,只能写在第一行。this.date,代表访问当前类中的成员属性。this.func(),代表调用当前类中的其他成员方法。注意:this并不代表当前对象,而是代表当前对象的引用,因为在当前类的构造方法中就已经可以使用this关键字了,而只有当构造方法完成之后该类的对象才算是被实例化出来。二、super关键字的用法super
2021-10-10 22:22:48
2241
原创 方法重写和重载的区别
一、 方法重载的特点:重载的方法的命名是相同的。返回值不作要求。互为重载关系的方法的参数列表不同,也就是参数类型或者参数个数等。需要在同一个类当中。二、方法重写的特点:重写方法的命名是相同的重写方法的返回值也需要是相同的,也可以是协变类型,也就是返回值之间构成继承关系。重写方法的参数列表也要相同。在不同的类当中,且所属类构成继承关系。...
2021-10-10 22:05:41
1567
原创 基于HTTP协议实现一个登录界面
处理请求public class HttpRequestV3 {//解析客户端发过来的HTTP请求, private String method; private String URL; private String verson; private Map<String,String> headers = new HashMap<>();//这个表示发过来的请求中的header。里面是一个个的键值对 private Map<Stri.
2021-08-10 08:39:01
829
原创 IO流的基本操作
我们都知道现如今绝大部分计算机的组成方式都是著名的冯诺依曼体系,其中有两个部分叫作输入设备和输出设备,输入设备就是键盘,鼠标等能将数据输入到内存中;输出设备就是显示器,音箱等能让数据以特殊的方式让我们感知到。那么输入设备和输出设备之间具体是如何打交道的呢?其实我们的这些硬件设备都被抽象成了一些文件保存在磁盘上,操作硬件的时候本质上就是在对这些文件进行读写。例如一个进程通过网卡发送以及接收数据,本质上就是在这个进程中对网卡设备抽象出来的文件进行读写操作,把内存中的数据写到网卡文件中就相当于是在发送数据;从网
2021-08-10 08:11:13
167
原创 TCP协议风格的回显客户端——服务器
TCP协议风格的客户端——服务器是Java中提供的另外一种版本,特点就是面向字节流进行网络传输数据。其中涉及到两个类ServerSocketSocket对于UDP协议风格来说,客户端和服务器之间的交互不需要进行连接,直接就可以以数据包的形式发送接收数据。对于TCP协议风格来说,客户端和服务器先得建立好连接,才能去执行后面的操作服务器端:主要分为两个步骤利用ServerSocket类来初始化服务器,给服务器指定ip和端口号。具体用法和UDP中的DatagramSocket一致进入主循环①
2021-08-04 02:50:59
302
原创 如何实现一个UDP协议风格的回显服务器
UDP协议风格的客户端——服务器程序的特点就是通过数据包进行传输数据,也就是发送接收数据的时候,是以一个数据包为基本单位。其中涉及的API有两个DatagramSocket,用于给服务器绑定端口号和ip来开启服务器。本质就是描述网卡文件的类。后续客户端就可以通过这两个来借助网络访问服务器DatagramPacket,这个类可以理解为就是一个数据包。服务器端:核心操作主要有两步初始化操作,也就是实例化Datagramsocket对象,给服务器绑定端口号和ip号。进入主循环:a.读取数据并
2021-08-03 18:54:32
122
原创 如何理解Mysql中的事务以及事务的隔离级别
把一组操作封装到一起,成为一个共同的执行单元,可以理解为就是一组SQL语句,此时这个执行单元就可以叫作事务。它是Mysql数据库中提供的重要机制。事务中的操作应该满足以下特性:原子性,一个事务应该是一个不可分割的工作单位,要么全都做了,要么全都没做。一致性,事务执行前后,数据应该处于合法状态。持久性,事务执行完毕之后,数据就被永久修改了,也就是写到磁盘里面 了。哪怕重启计算机,也不会改变。隔离性, 多个事务并发执行时,事务之间互不干扰,本质上就是线程安全。其中,隔离性是最难理解的一点,隔
2021-07-29 02:35:44
121
原创 如何实现一个“线程池”
线程池里面包含了许多线程,可以供我们去使用,而避免了频繁的创建线程以及销毁线程,主要目的就是为了提高开发效率。那么我们如何实现一个自己的“线程池”呢首先我们来看一下线程池的组成部分有哪些有一个类,这个类表示工作线程,也就是用来执行任务的线程,借助这个类可以表示多个线程还得有一个类来描述具体线程要做的任务是什么,直接使用Runnable即可还需要一个阻塞队列来组织若干个任务。好需要一个List来组织若干个线程线程池核心操作execute创建线程并且将要执行的任务放到阻塞队列中去。shu
2021-07-28 02:22:33
498
原创 如何实现一个“定时器”
定时器是多线程编程中的一个重要且常用的组件,顾名思义,定时器好比一个闹钟一样,必须得等指定时间到了才会去执行任务。那么我们该如何来实现一个简单的定时器呢首先我们来认识一下定时器的构成使用一个Task类来描述一段逻辑,也就是要执行的任务,并且记录好这个任务在什么时候来执行。使用一个阻塞优先队列来组织若干个Task,使用优先队列就是为了保证队首的任务就是最早需要被执行的那个任务还需要一个扫描线程,来时刻扫描是否有任务的执行时间到了。如果到了就去执行这个任务。下面我们来看具体代码public cl
2021-07-28 02:00:01
294
原创 如何实现一个阻塞队列
认识阻塞队列之前我们先来看看生产者——消费者模型。类比于包饺子,把包饺子分为两件事,擀面皮和包饺子。擀面皮就可以理解为生产者,包饺子可以理解为消费者.此时就会涉及到两种情况生产者生产得快,消费者消费得慢。此时放饺子的那个交易所上面慢慢的就会放满饺子。这个时候就应该让生产者阻塞等待。生产者生产得慢,消费者消费得快。此时放饺子的那个交易所上面慢慢的就会没有饺子。这个时候就应该让消费者阻塞等待。阻塞队列就是用来实现生产者——消费者的。当我们入队列的时候发现队列已经满了,就应该让入队列操作阻塞等待;出队列
2021-07-27 13:48:31
718
3
原创 如何解决单例模式中多线程并发导致的问题
单例模式,是设计模式中的一种。顾名思义,单例就是单个实例的意思,也就是说在代码中保证指定的类只有一个,如果创建了多个指定类的实例,直接让编译器报错。单例模式的实现方式主要有两种饿汉模式public class Practice {//饿汉模式 private Practice() {//将构造方法设置成私有 } static Practice p = new Practice(); public static Practice getPractice() {//通
2021-07-25 22:56:31
1276
原创 对象等待集如何解决“线程饿死”
我们知道多线程执行的时候是抢占式执行的,这样虽然大大提高了效率,但是也会导致许多问题出现,可以说是有利有弊。“线程饿死”就是其中一个弊端。当我们在多个线程中加入锁之后,由于这些线程是抢占式并发执行的,这些线程就会去竞争这把锁,当某一个线程竞争到锁之后,如果由于缺乏某些条件导致CPU没有执行该线程,然后该线程释放锁之后还会继续去参与竞争。如果极端情况下一直都是该线程抢到锁,其他线程一直处于阻塞状态,就像没有抢到食物被饿死了一样,这就叫做“线程饿死”现象。这种现象会大大降低程序执行效率,因为其他线程长时间执行
2021-07-23 07:18:15
445
原创 内存可见性如何导致线程不安全
除了多个线程同时修改同一个变量会导致线程不安全之外,还有一种情况就是内存可见性,我们首先来看一段代码public class ThreadDemo14 { static class counter { public volatile int flag = 0; } public static void main(String[] args) { counter c = new counter(); Thread t1 = new
2021-07-23 06:32:22
184
2
原创 多线程带来的风险以及解决办法
多线程虽然能大大提高CPU执行效率,但是也并不是百利无一害,也有线程不安全的情况存在,这也是多线程并发中涉及到的最重要也是最复杂的问题。那么什么是线程不安全呢?概括来说,线程不安全的原因在于多并发执行某行代码的时候,产生了逻辑上的错误,这就叫做线程不安全。那么什么是逻辑上的错误呢?我们以具体代码来解释class counter {//计数器 public int count = 0 ; public void incr() { count++; }}publ
2021-07-21 04:08:52
765
1
原创 线程的基本操作
要想掌握多线程编程,线程的基本操作必不可少,下面就列举一下线程的一些基本操作一、创建线程创建线程的方式广泛来说一共有五种通过继承Thread类来创建public class Practice { static class MyThread extends Thread { @Override public void run() { System.out.println(("哈哈")); } } pu
2021-07-21 03:00:12
436
1
原创 操作系统——线程
进程可以理解为是一个程序的执行过程,如果以进程为CPU调度单位的话,太消耗性能,因为每次调度都是以整个进程为单位,所以引入了线程的概念。所谓的线程,其实是包含在进程中的,如果把进程想象成一个工厂的话,那么线程就是工厂中的一条条流水线,每一个线程都有一段自己要执行的命令逻辑,也就是每个线程都是一个独立的执行流。同一个进程中的线程共享着许多的资源,所以创建一个线程是比创建一个进程成本要低的,销毁也是。当前也有一些不能共享的资源,每个线程要独立的参与CPU的调度,所以每个线程的PCB后面四个属性都不是共享的线
2021-07-19 16:51:56
89
原创 操作系统——进程
操作系统是一台计算机必不可少的部分,一个完整的操作系统应该包含两个部分——操作系统内核+一系列软件。其中一系列软件就是我们平常使用的软件,而内核则是我们主要需要认识的部分。在认识内核之前,我们首先来认识一下计算机的硬件组成。目前百分之99的计算机都是由冯诺依曼体系构成,例如手机,笔记本,台式机,云服务器等等。冯诺依曼体系描述了一台计算机应该包含以下部分CPU,即中央处理器,是一台计算机最核心的部分。存储器,这里的存储器主要是指内存储器,主要用于CPU和其他硬件打交道,其他硬件设备要想接触到CPU,都
2021-07-19 16:12:17
255
原创 什么是数据库索引
什么是索引索引,英文单词为index,可以把他比作一本书的目录,本质就是为了加快查找效率,如果数据库中没有索引,当我们要进行查找的时候就要把整个表都遍历一遍,类似于遍历顺序表。但是比顺序表会更慢,因为数据库存储的数据都是在磁盘上,计算机访问磁盘的效率远远低于访问内存。当数据库中数据量非常多的时候,效率会非常非常低。索引的最终目的就是为了避免顺序查找,加快查找效率。索引的底层数据结构索引的底层数据结构首先我们知道索引可以考虑的数据结构有两种,二叉搜索树和哈希表。因为顺序表链表查找方式和数据表本质上没.
2021-07-04 20:42:16
514
2
原创 Mysql增删改查
CRUD,即增加Create,查询Retrieve,Updata更新,删除Delete。其中增删改都差不多,而查询的话玩法比较多。下面就来具体看看如何对表进行增删改查一、增加sql语句:insert into +表名 +values (要增加的字段内容)。需要注意插入的字段内容需要和我们创建表规定的每列的类型保持一致。在sql语句中字符串可以用单引号也可以用双引号。也可以指定列来插入,也就是只插入到指定列中sql语句:insert into +表名+(要插入的列名)+values+(对应的字
2021-07-04 20:00:57
82
原创 如何使用Mysql数据库
首先,数据库分为两大类——关系型和非关系型。关系型数据库组织数据的形式类似excel,有行有列,表中的一行就是一条记录,这些记录全都存储在磁盘上,表中的每一列的类型由我们建表的时候定义,每一行的每一列都需要和表头类型一致,对于数据的约束比较强。常见的关系型数据库有Mysql,Oracle,sql server等等。而非关系型数据库对于数据的组织采用键值对的形式,类似于集合中的map,存储的时候需要指定key和value,对于数据的约束比较低。常见的非关系型数据库有redis,mongodb等等。关系型数据
2021-07-04 16:06:30
542
1
原创 如何实现一个哈希表
哈希表在Java集合中属于HashSet和HashMap的底层实现,它的查找效率非常的高,优于前面所学的链表顺序表,二叉搜索树等等,并且更是作为现代分布式系统的基础,由此可见它在众多数据结构中的重要性,下面具体实现一个哈希表。哈希表主要由两个部分组成1.一个数组2.记录实际元素个数的变量size具体实现过程就是把我们需要存储的元素映射成数组下标进行存储,当需要对哈希表进行操作的时候就根据映射出来的这个哈希值来访问具体的元素。比如说给定我们若干个数字0——99之间,然后我们需要判断哪个数字是否存在于
2021-06-27 20:28:04
546
1
原创 二叉搜索树
二叉搜索树在集合类中对应到TreeSet,TreeMap的底层实现,它属于一种特殊的二叉树,对比于普通的二叉树,它的特殊之处在于左子树的所有值都小于根节点,而右子树的所有值都大于根节点。所以我们根据中序遍历二叉搜索树就可以得到一个有序的序列。顾名思义,二叉搜索树的最大的用处在于查找,如果我们要查找一个元素,就把它和根节点进行比较,如果小于根节点,就去左边找,如果大于根节点,就去右边找。大大提高了查找效率,一般情况下时间复杂度可达O(logN),除非这颗树二叉搜索树特别的不一般,那就是只有单边树的情况,这样的
2021-06-26 18:23:35
81
原创 坏掉的键盘问题
问题描述:旧键盘上坏了几个键,于是在输入的时候,对应的字符就不会出现,现在给出应该输入的一串文字,以及实际被输入的文字,请你列出肯定坏掉的键盘键。public class BrokenKey { //1.循环读入两个字符串 //2.把读入的字符串全部转为大写 //3.题目的要求是判断预期输入的哪些字符在实际输出中不存在,不存在的这些就是坏掉的键 //需要注意的是预期输入中输入了多次字符母,但是最后的结果只有一个。所以最后还得对坏掉得键进行去重(Set) public
2021-06-25 18:19:53
104
原创 给定一个非空整数数组,除了某个元素只出现一次之外,其余的都出现两次,找出只出现一次的那个数字
可以借助Mappublic class Haha { public static void main(String[] args) { int[] arr = {1, 2, 2, 3, 3,3}; Find(arr); } private static void Find(int[] arr) { Map<Integer, Integer> map = new HashMap<>(); fo.
2021-06-25 18:04:54
604
原创 对象之间的比较
实现比较的方式一共有三种==.equalsComparableComparator其中等号比较的是对象的身份,也就是它们的地址是否相同,.equals比较的是对象自身,Comparable和Comparator都是可以比较对象的大小关系,具体根据什么进行比较我们可以自己定义一、==class Card { public String rank;//扑克牌的点数 public String suit;//扑克牌的花色 public Card(String rank,
2021-06-23 12:52:20
227
原创 归并排序怎么玩
思路:递归将待排序区间划分为两段,如果这两段是有序的的话,把它们一合并就可以了。递归的终止条件就是当某个待排序区间里面只有一个元素的时候,那么此时这个区间就一定是有序的了。public class MergeSort {//归并排序 public static void main(String[] args) { int[] arr = {9,5,2,7,3,6,8}; mergesort(arr); System.out.println((Arr
2021-06-22 11:20:00
65
原创 快速排序的非递归实现
思路:借助栈来模拟实现public class quikesortbyloop {//快速排序的非递归实现 public static void main(String[] args) { int[] arr = {9,5,2,7,6,4,8}; quikesortbyLoopp(arr); System.out.println((Arrays.toString(arr))); } public static void quike
2021-06-22 11:12:22
83
原创 快速排序怎么玩
思路:在待排序区间中找到一个基准值,然后以基准值为中心,将整个待排序区间整理成三个部分,基准值左边都是小于它的,基准值右边都是大于它的,最后再去递归处理左侧的区间,递归处理右侧的区间。示例代码:public class QuikeSort {//快速排序 public static void main(String[] args) { int[] arr = {9,5,2,7,3,6,8,10,-1,4}; quikesort(arr); Sys
2021-06-22 11:09:26
52
原创 冒泡排序的玩法
核心目标和堆排序,选择排序类似,也是每次找到一个最小值或者最大值放在合适的位置。不过冒泡排序借助的是相邻元素来进行比较交换public static void main(String[] args) { int[] arr = {9,5,2,7,3,6,8}; Bulllesort(arr); System.out.println((Arrays.toString(arr))); } public static void Bulllesor
2021-06-15 22:46:08
48
3
原创 堆排序的玩法
堆排序一共有两种风格都以升序排序为例将待排序数组建成一个小堆,每次取堆顶元素后放入一个数组中。然后再向下调整继续进行。把数组建成一个大堆,堆顶就是当前数组的最大值,然后把堆顶元素和最后一个元素进行互换,再把最后一个元素从堆里面删除,...
2021-06-15 22:18:08
59
原创 选择排序的玩法
选择排序利用的是打擂台的思想,每次和擂主进行比较,然后谁小谁就当擂主。public static void main(String[] args) { int[] arr = {5, 3, 6, 8, 9, 1, 2}; insertsort(arr); System.out.println((Arrays.toString(arr))); } public static void insertsort(int[] arr) {
2021-06-15 21:17:09
47
原创 希尔排序的玩法
希尔排序可以理解为是插入排序的进阶版,先将需要排序的数组分为gap组,再针对每一组进行插入排序,逐渐缩小gap的值,在缩小的时候数组会变得越来越有序,当gap为1的时候也就是对整个数组进行插入排序。 public static void main(String[] args) { int[] arr = {5, 3, 6, 8, 9, 1, 2}; insertsort(arr); System.out.println((Arrays.toString(ar
2021-06-15 21:07:29
54
原创 插入排序的玩法
public static void main(String[] args) { int[] arr = {5,3,6,8,9,1,2}; insertsort(arr); System.out.println((Arrays.toString(arr))); } public static void insertsort(int[] arr){ for(int bound = 1;bound<a...
2021-06-15 20:32:16
52
原创 给定两个以升序排列的整型数组以及一个整数K,定义一对值(u,v),其中第一个元素来自数组1,第二个元素来自数组2,找出和最小的K对数组
public class test { static class Pair implements Comparable<Pair>{ public int s1; public int s2; public int sum = s1+s2; public Pair(int s1, int s2) { this.s1 = s1; this.s2 = s2;
2021-06-13 05:49:29
587
1
原创 数据结构——堆
概念:堆也叫做优先级队列,入队列的时候同样是和普通队列一样入,但是出队列的时候优先出优先级较高的元素,优先级相同的情况下再按照先进先出的方式进行。堆的实质实际是一棵二叉树,并且这颗二叉树需要满足以下三个条件:①:满足完全二叉树的条件,也就是当某个节点没有子节点或者没有右节点之后,它后面的所有节点都不能再有子节点。②:对于整棵树中的任意某颗子树,都要满足根节点的值小于或者大于左右子节点的值,称为小堆和大堆。并且满足小堆就不可能满足大堆,反之亦然。堆通常通过数组来进行存储,通过层序遍历一棵满足以..
2021-06-13 05:30:02
301
1
原创 通过二叉树前序遍历的结果还原二叉树
private static int index;//定义一个静态变量,来指定字符的位置,为了能时刻直到当前访问到字符串中的哪个元素。因为静态的只有一份,会一直增加 public static Node build(String line) { index = 0; return creatTreePrev(line);//创建一个方法来创建节点 } public static Node creatTreePrev(String line){ cha.
2021-06-11 04:19:38
595
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人