有趣的Java-J02

来源:互联网 发布:东莞plc编程培训机构 编辑:程序博客网 时间:2024/05/19 17:26

1.HashMap的放入元素后的排列顺序跟什么有关?

解决这个问题需要你对HashMap底层原理有所了解,HaspMap的底层是由数组(实际上可以看作是哈希表)和单链表实现的,放入的元素先通过hashCode()方法得到一个哈希值然后再通过一系列运算,最终得到一个值,然后再进行Mod(取余运算)运算确认这个元素是位于数组的哪个位置,比如:当你执行语句hashMap.put(a,b),那么这个key为a的元素在哪个位置是这么运算的:
1.取得key的哈希值,通过a.hashCode()方法得到哈希值hashInt
2.计算mod值,假设当前HashMap集合底层的数组长度为n,那么mod = hashInt%n
3.通过mod值就可以确认此元素在数组中的位置,比如mod =3,那么此元素就位于数组中的第4个
4.接下来,再通过hashInt值确认在数组第mod+1个位置对应的单链表的位置,这里其实很简单,就是对单链表从头至尾一个一个进行遍历,当发现hashInt值小于这个已经存在的元素对应的hashInt值时,那么就插入添加到这个已存在的元素的上一个位置。这样就是完成元素的放入了。

看看下面的图,你就应该懂了:
这里写图片描述

详细理解请看以下链接:
http://blog.csdn.net/vking_wang/article/details/14166593

2.HashMap如何解决哈希冲突(哈希碰撞)?

哈希冲突(哈希碰撞)是什么意思,你首先得懂?先来看看哈希冲突的四种解决方法:
http://blog.csdn.net/qq_27093465/article/details/52269862

那么HashMap是如何解决哈希冲突的呢?
http://www.cnblogs.com/peizhe123/p/5790252.html

3.讲讲List集合的特性?并且封装一个类去模拟LinkedList的功能,基本的增删改查以及迭代器

List集合特点:有序可重复
有序可重复:有序是指集合内元素排列顺序是按照放入的顺序排列的,可重复指的是可以放入一样的元素
实现了接口该接口的集合:ArrayList,LinkedList,Vector,详细看以下链接:
http://blog.csdn.net/wz249863091/article/details/52853360?locationNum=3&fps=1

模拟LinkedList代码:

public class LinkedListCopy<E> {    private Node<E>  head = new Node<>(null);//整个单链表的头部    private int size =0;//单链表的长度    //结点类    private static class Node<E>{        public Node head = null;//结点的头部        public Node tail = null;//结点的尾部        E value;//结点中存放的值        public Node(E e){value = e;}    }    //迭代器类    private static class DieDaiQi<E>{        private LinkedListCopy<E> linkedListCopy;//模拟被迭代的LikedList        private Node<E> dangQian ;//存放处于焦点的结点        public DieDaiQi(LinkedListCopy<E> linkedListCopy){            this.linkedListCopy = linkedListCopy;            dangQian = linkedListCopy.head;//当你生成迭代器的时候,焦点开始在整个单链表的头部        }        //将当前的焦点移动一格        public boolean moveToNext(){            boolean falg = (dangQian.tail != null);            dangQian = dangQian.tail;            return falg;        }        //获取当前焦点对应的结点的值        public E next() {            E e = dangQian.value;            return e;        }        //重置迭代器        public void reSet(){            dangQian = linkedListCopy.head;        }    }    public LinkedListCopy(){    }    //获取当前单链表的迭代器    public DieDaiQi dieDaiQi(){         return new DieDaiQi(this);    }    //尾部添加元素    public void add(E e){        Node<E> dangQian = this.head.tail; //存放焦点对应的结点        Node<E> ago = head; //存放当前焦点前一个的结点        while(true) {             if(dangQian!=null){                //没有移动到尾部,将焦点移动一格                ago = dangQian;                dangQian = dangQian.tail;             }else {                //当移动道尾部的时候,就可以添加元素                dangQian = new Node<E>(e);                if(ago.tail == null){                    ago.tail = dangQian;                    dangQian.head = ago;                }                break;             }        }        size++;//添加元素,长度加1    }    //在指定位置插入元素    public void add(int i,E e){         if(i<0||i>=size()){             System.out.println("越界异常");             return;         }        if( i == this.size()){this.add(e);return;}//尾部插入        //插入添加        Node<E> node = new Node<>(e);        Node<E> dangQian = this.head.tail;//存放焦点对应的结点        Node<E> ago = this.head;//存放当前焦点前一个的结点        int j = 0;        while(dangQian != null)        {            if(i == j){                node.head = ago;                node.tail = dangQian;                dangQian.head = node;                ago.tail = node;                break;            }else{                j++;                ago = dangQian;                dangQian = dangQian.tail;            }        }        size++;//添加元素,长度加1    }    //删除元素    public void delete(int i){        if(i<0||i>=size()){            System.out.println("越界异常!");            return;        }        Node<E> dangQian = this.head.tail;        Node<E> ago = head;        int j=0;        while(dangQian != null){            if(j == i){                ago.tail = dangQian.tail;                dangQian.tail.head = ago;                break;            }else{                j++;                ago = dangQian;                dangQian = dangQian.tail;            }        }        size--;//删除元素长度减一    }    //修改元素    public void gaiValue(int i,E e){        if(i<0||i>=size()){             System.out.println("越界异常");             return;        }        Node<E> dangQian = this.head.tail;        Node<E> ago = null;        int j=0;        while(dangQian != null){            if(j == i){                dangQian.value = e;                break;            }else{                j++;                ago = dangQian;                dangQian = dangQian.tail;            }        }    }    //查询元素    public int serach(E e){        Node<E> dangQian = this.head.tail;        int j=0;        while(dangQian != null){            if(dangQian.value.equals(e)){                return j;            }else{                j++;                dangQian = dangQian.tail;            }        }        return -1;    }    //获取当前单链表的长度    public int size(){       return  size;    }    //尾部添加另外一个单链表    public void addAll(LinkedListCopy<E> linkedListCopy){        Node<E> dangQian = linkedListCopy.head.tail;        while(dangQian != null){            this.add(dangQian.value);            dangQian = dangQian.tail;        }    }    //获取集合指定位置的元素值    public E get(int i){        if(i<0||i>=size()){            System.out.println("越界异常");            return null;        }        Node<E> dangQian = this.head.tail;        int j=0;        while(dangQian!=null){            if(j == i){                return dangQian.value;            }else{                j++;dangQian =dangQian.tail;            }        }        return null;    }    //还有其它的功能可以模拟,代码较多,笔者就不写了,理解上面的迭代器原理,什么都可以模拟的出来    public static void main(String[] args){        LinkedListCopy<String> linkedListCopy = new LinkedListCopy<String>();        DieDaiQi<String> dieDaiQi = linkedListCopy.dieDaiQi();//获取迭代器        //尾部增加        linkedListCopy.add("ss1");        linkedListCopy.add("ss2");        linkedListCopy.add("ss3");        linkedListCopy.add("ss4");        System.out.println("1*****尾部添加操作*****");        System.out.println("尾部添加操作后集合所有元素如下:");        while (dieDaiQi.moveToNext()){             System.out.println(dieDaiQi.next());        }        System.out.println("此时集合元素个数:"+linkedListCopy.size());        System.out.println("1*****尾部添加操作*****\n");        //插入添加        linkedListCopy.add(0,"ss");        linkedListCopy.add(3,"ss2.5");        dieDaiQi.reSet();//重置迭代器        System.out.println("2*****插入添加操作*****");        System.out.println("插入添加操作后集合所有元素如下:");        while (dieDaiQi.moveToNext()){             System.out.println(dieDaiQi.next());        }        System.out.println("此时集合元素个数:"+linkedListCopy.size());        System.out.println("2*****插入添加操作*****\n");        //删除        linkedListCopy.delete(3);        dieDaiQi.reSet();//重置迭代器        System.out.println("3*****删除操作*****");        System.out.println("删除操作后集合所有元素如下:");        while (dieDaiQi.moveToNext()){             System.out.println(dieDaiQi.next());        }        System.out.println("此时集合元素个数:"+linkedListCopy.size());        System.out.println("3*****删除操作*****\n");        //修改        linkedListCopy.gaiValue(0,"ss0");        dieDaiQi.reSet();//重置迭代器        System.out.println("4*****修改操作*****");        System.out.println("修改操作后集合所有元素如下:");        while (dieDaiQi.moveToNext()){             System.out.println(dieDaiQi.next());        }        System.out.println("此时集合元素个数:"+linkedListCopy.size());        System.out.println("4*****修改操作*****\n");        //查询操作        int serachInt  = linkedListCopy.serach("ss8");        if(serachInt==-1) {            System.out.println("集合中不存在该元素!");        }else{            System.out.println("ss3存在的位置是:第" + (serachInt + 1) + "个");        }        System.out.println(linkedListCopy.get(serachInt));    }}

4.序列化与反序列,序列化是干嘛用的?

序列化是干嘛用的呢?序列化和反序列化怎么做?很多人到现在都还不懂,不妨看看以下链接:
http://blog.csdn.net/dreamtdp/article/details/15378329

5.Set集合如何保证无序性和唯一性?

Set集合的无序性指的是元素的排列顺序不会按照放入的元素的顺序进行排列
Set集合的唯一性指的是放入的元素不能重复相同,也就是Set集合中的每一个元素都不相同

Java中Set集合存在两个实现的类,一个是HashSet,另外一个是TreeSet,那我们一个一个来看看它们是如何实现无序性和唯一性的:

1.HashSet(底层是哈希表)

无序性实现: 用到元素对象的hashCode()方法,通过哈希值来确定元素在哈希表中的位置,所以是无序的。

唯一性实现: 用到元素对象的hashCode()和equals()方法,其实就是把判断加入的元素与集合中已经存在元素进行一一比较,判断是否为为相同元素。首先元素对应哈希值不同,那么这两个元素肯定不相同,如果哈希值相同,那么还不能说明这两个元素是相同的,还需要进行equals()方法调用,当equals()方法返回true时,说明这两个元素相同,当返回false则说明这两个元素不相同。比较流程如下图所示,笔者以前画的图吗,凑合凑合,哈哈:

因此,当你往HashSet里面添加自定义类对应的对象时,最好让你的自定义类重写hashCode()方法和equals()方法。

2.TreeSet(底层是树)

无序性的实现: 排序规则是默认使用元素的自然排序,或者根据实现Comparable接口(比较器)的compareTo()方法进行排序。也就是当你不给TreeSet比较器接口Comparable,那么就是自然排序,否则,就会按照给的接口Comparable接口(比较器)的compareTo()方法进行排序。

唯一性的实现:判断重不重复也是通过compareTo()方法来完成的,当compareTo()方法返回值为0时,两个对象是相同的。当compareTo()方法返回值为正数时,调用compareTo()方法的元素对象大于另外一个元素对象,为负数时,不用我说了吧,所以存入TreeSet集合的对象对应的类一定要实现Comparable接口。

下篇问题预览:

1.动态代理是什么?如何实现?什么场景使用

2.动态代理和静态代理区别

3.代码混淆是是什么意思?作用?怎么进行代码混淆

4.什么是深克隆?什么是浅克隆?clone()方法是深克隆还是浅克隆?

5.new一个对象的过程和clone一个对象的过程区别

有趣的Java-J03
传送门:http://blog.csdn.net/clandellen/article/details/77816212

原创粉丝点击