兄弟们,今天咱们主动出击!干掉秃头老!然后带他植发去!(若不知道秃头老是啥玩意,请看这篇文章!,打波小广告)
旁白:默默的走向秃头老工位,拍了一下老秃的小脑袋瓜。
我:秃头哥,咱们今天再战一下?
老秃头:谁TM叫秃头哥,叫我技术佬!行啊,那今天我们玩点不一样的,不单干某个知识点了,来一个知识点随机考察!来看看小兔崽子有多少墨水!
我:好啊,来吧谁怂谁是小王八!(呦呦呦,还技术佬,啊…呸!)
秃子:咱们都知道HTTP请求是无状态的,那他是如果解决无状态问题的那?(搞个无厘头的,试试水,虽然我也不会)
我:(wc,什么鬼!但是老子知道一点!)这个主要是通过Cookie来实现无状态存储的,过程是这样的:
1:Cookie通过HTTP向Server发送请求
2:Server收到请求后,设置Cookie头部信息,返回给客户端
3:客户端收到后保存Cookie头信息,然后每次请求都带上
4:Server通过Cookie就知道是哪个Client了,然后会做出相应的反应!
秃子:(这…有点意思哦!)那ArrayList 如何实现动态增长的?
我:(您可是真随机呀!)这不是我前两天发的那个Arraylist源码分析里面的嘛,那我就简单的说一下。先看add()
方法,里面调用了ensureCapacityInternal()
方法,这个方法会计算最小扩容量minCapacity,然后在调用ensureExplicitCapacity()
方法判断是否需要进行扩容,也就是grow()
方法,此方法主要是先获取老数组容量大小,然后扩容1.5倍,最后利用Arrays.copyOf()
进行数组迁移
秃子:(哎呦,记忆力可以哦,这只是小试牛刀)那既然说到了ArrayList,那肯定知道LinkedList把,什么时候会用到那?
我:那必须知道嘛,老熟悉了!ArrayList每次容量快满的时候就会进行1.5倍扩容,如果数据量很大的话就会造成空间的极大浪费!而LinkedList可以做到用多少申请多少!场景的话,如下:
1、当频繁的在尾部添加,删除元素,动态数组,双向链表都可以
2、频繁的头部添加,删除元素,建议双向链表
3、频繁的在任意位置添加,删除元素,建议双向链表
4、频繁的查询任意位置元素,建议使用动态数组
秃子:(哎呦,答得凑乎,我在随机一个!)慢查询知道吧,一般如何进行sql优化那?
我:(哎呦,知道我对集合还是了解一点的哦,不过目前只有List的,陆续推出Map等等,莫慌哦兄弟们!)一般我们会在where,group by,order by后面的字段建立索引来解决,但是建立索引的时候需要注意这几点,否则就会发生索引失效的情况,从而导致全表检查!比如:
1、where条件中不要用<>
或者!=
不等于号
2、where条件中不要用is null
3、where条件中不要用%abc%
4、where条件中谨慎使用in
和not in
5、where条件中尽量不要对字段使用表达式或者函数,eg:num / 2 = 100
,left(time,4) = '2021'
等等!
秃子:那复合索引用过吗,什么时候会引起失效那?
我:一般多个字段条件的时候会用到,它是遵循最左匹配原则的,比如给key index (a,b,c)
三个字段建立索引,一般索引生效的情况就是a|ab|abc
三种情况!
秃子:那你知道索引的底层实现嘛?(既然说起了索引,那不得把你问的跪地求饶嘛!)
我:(这这这…,索引这块还是有所欠缺,大家持续关注一波哦,陆续会发出来详细解析,挖个坑,哈哈哈哈)嗯…索引的就是为了提高查询效率的数据结构,并且存储在文件中,底层实现是B/B+
树,而B/B+
其实就是平衡的M阶的树,而他两个区别就是B树每个节点都存储关键字和地址,而B+非叶子节点存储关键字,叶子节点存储数据,并且每个叶子节点构成了有序的链表比较适合区间查找!
旁白:此时,有一个精神小妹走到秃头老的身边,悄咪咪的说了几句话,说完秃头老色迷迷的笑起来了!
秃子:今天先到这,我这还有点事情,我给你来三道算法题,你尝试一下,都很简单!
我:(老秃子,去约会了吧,还有点事情,就你那色迷迷的眼神出卖你了!)哦…这样啊,没事,那你出几道题,就走吧!
第一题:二分查找
public int search(int[] nums, int target) {
int l = 0;
int r = nums.length - 1;
while (l <= r){
int m = l + ((r - l) >> 2);
if (nums[m] == target) return m;
else if (nums[m] > target) r = m - 1;
else if (nums[m] < target) l = m + 1;
}
return -1;
}
第三题:奇升偶降
/**
* @author: tianjx
* @date: 2021/12/19 16:21
* @description: 奇偶排序
* 输入:1->8->3->6->5->4->7->2->NULL
* 输出:1->2->3->4->5->6->7->8->NULL
* 思路:
* 1、拆分成奇偶链表
* 2、反转偶链表
* 3、合并输出
*
*/
public class OddEvenLinkedSort {
static class ListNode{
int val;
ListNode next;
public ListNode(int val){
this.val = val;
}
public ListNode(int val, ListNode next){
this.val = val;
this.next = next;
}
}
/**
* 链表反转
* @param head
* @return
*/
public static ListNode reverse(ListNode head){
if (head == null) return null;
ListNode pre = null;
ListNode curr = head;
while (curr != null){
ListNode tmp = curr.next;
curr.next = pre;
pre = curr;
curr = tmp;
}
return pre;
}
/**
* 链表合并
* @param h1
* @param h2
* @return
*/
public static ListNode merge(ListNode h1, ListNode h2){
ListNode dummy = new ListNode(-1);
ListNode p = dummy;
while (h1 != null && h2 != null){
if (h1.val <= h2.val){
p.next = h1;
p = p.next;
h1 = h1.next;
}else{
p.next = h2;
p = p.next;
h2 = h2.next;
}
}
p.next = h1 == null ? h2 : h1;
return dummy.next;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
String str= scan.next();
String[] split = str.split("->");
int oddIndex = 0;
int evenIndex = 0;
ListNode[] oddNodes = new ListNode[split.length - 1];
ListNode[] evenNodes = new ListNode[split.length - 1];
for (int i = 1; i <= split.length - 1; i++) {
if (i % 2 == 1) oddNodes[oddIndex++] = new ListNode(Integer.valueOf(split[i - 1]));
else evenNodes[evenIndex++] = new ListNode(Integer.valueOf(split[i - 1]));
}
for (int i = 0; i < oddIndex - 1; i++) {
oddNodes[i].next = oddNodes[i + 1];
}
for (int i = 0; i < evenIndex - 1; i++) {
evenNodes[i].next = evenNodes[i + 1];
}
ListNode evenReverse = reverse(evenNodes[0]);
ListNode merge = merge(oddNodes[0], evenReverse);
String result = "";
while (merge != null){
result += merge.val;
result += "->";
merge = merge.next;
}
System.out.println(result += "NULL");
}
}
最后的最后:
兄弟们,今天的随机考察到此结束,记得关注一下,后续陆续推出HashMap,ConcurrentHashMap,索引等等知识点,终极篇的话是秃头老植发,兄弟们持续关注一波哦!