您的位置:首页 > 职场人生

面试-java基础

2017-05-15 10:19 232 查看
1.collection和collections

2.linkedlist和arraylist

4.set  不含重复元素   list可重复

    hashset存储add():依赖hashcode()  equals()

先比较hash值,不同就添加到集合中,相同时再比较地址值,相同equal()则为重复元素,不添加。不同就添加到集合中

3.hashmap:hash值是逻辑值,地址值是实际值,有hash值相同地址值不同的情况

hash表: 一个元素是链表的数组

 * HashSet:存储字符串并遍历

 * 问题:为什么存储字符串的时候,字符串内容相同的只存储了一个呢?

 * 通过查看add方法的源码,我们知道这个方法底层依赖 两个方法:hashCode()和equals()。

 * 步骤:

 * 首先比较哈希值

 * 如果相同,继续走,比较地址值或者走equals()

 * 如果不同,就直接添加到集合中

 * 按照方法的步骤来说:

 * 先看hashCode()值是否相同

 * 相同:继续走equals()方法

 * 返回true:
说明元素重复,就不添加

 * 返回false:说明元素不重复,就添加到集合

 * 不同:就直接把元素添加到集合

 * 如果类没有重写这两个方法,默认使用的Object()。一般来说不同相同。

 * 而String类重写了hashCode()和equals()方法,所以,它就可以把内容相同的字符串去掉。只留下一个。

源码:

<code>

interface Collection {
...

}

interface Set extends Collection {
...

}

class HashSet implements Set {
private static final Object PRESENT = new Object();
private transient HashMap<E,Object> map;

public HashSet() {
map = new HashMap<>();
}

public boolean add(E e) { //e=hello,world

        return map.put(e, PRESENT)==null;

    }

}

class HashMap implements Map {
public V put(K key, V value) { //key=e=hello,world

//看哈希表是否为空,如果空,就开辟空间

        if (table == EMPTY_TABLE) {

            inflateTable(threshold);

        }

        

        //判断对象是否为null

        if (key == null)

            return putForNullKey(value);

        

        int hash = hash(key); //算一个hash值,和对象的hashCode()方法相关

        

        //在哈希表中查找hash值

        int i = indexFor(hash, table.length);

        for (Entry<K,V> e = table[i]; e != null; e = e.next) {

        //这次的e其实是第一次的world

            Object k;

            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {

                V oldValue = e.value;

                e.value = value;

                e.recordAccess(this);

                return oldValue;

                //走这里其实是没有添加元素

            }

        }

        modCount++;

        addEntry(hash, key, value, i); //把元素添加

        return null;

    }

    

    transient int hashSeed = 0;

    //算哈希值

    final int hash(Object k) { //k=key=e=hello,

        int h = hashSeed;

        if (0 != h && k instanceof String) {

            return sun.misc.Hashing.stringHash32((String) k);

        }

        h ^= k.hashCode(); //这里调用的是对象的hashCode()方法

        // This function ensures that hashCodes that differ only by

        // constant multiples at each bit position have a bounded

        // number of collisions (approximately 8 at default load factor).

        h ^= (h >>> 20) ^ (h >>> 12);

4000

        return h ^ (h >>> 7) ^ (h >>> 4);

    }

}

hs.add("hello");

hs.add("world");

hs.add("java");

hs.add("world");

</code>

推荐一个:
http://www.cnblogs.com/ITtangtang/p/3948406.html
short s=1;s=s+1; short s=1;s+=1; 有区别么?? 如果有的话区别是什么? 没有的话值是多少?

short s=1; 

s=s+1; 

自然是编译不通过的 提示损失精度 

那么 

short s=1; 

s+=1; 

为什么能编译通过那? 

还有一个问题 

隐式类型转换可以从小到大自动转,即byte->short->int->long如果反过来会丢失精度,必须进行显示类型转换 

s+=1的意思与s=s+1不同,

s=s+1这句先执行s+1然后把结果赋给s,由于1为int类型,所以s+1的返回值是int,

                 编译器自动进行了隐式类型转换所以将一个int类型赋给short就会出错,

而s+=1不同由于是+=操作符,在解析时候s+=1就等价于s = (short)(s+1),翻番来讲就是 

                 s+=1 <=> s =  (s的类型)(s+1)

异常:

异常分类:
编译时被检查异常; ---> Checked异常,在程序中必须使用try...catch处理;

Java编译器会检查它,也就说程序中一旦出现这类异常,要么是没有try-catch语句捕获,或throws语句没有声明抛出它,编译就不会通过,也就说这种异常,程序要求必须处理.

编译时不被检测的异常;
---> Runtime异常,可以不使用try...catch处理,但一旦出现异常就将由JVM处理。
  这种异常Java编译器不会检查它,也就说程序中出现这类异常的时候,即使不处理也没有问题,但是一旦出现异常,程序将异常终止,若采用异常处理,则会被相应的程序执行处理.   

String  不可变类,一旦String对象被创建,包含在对象中的字符序列(内容)是不可变的,直到对象被销毁;

常量池:JVM中一块独立的区域存放字符串常量和基本类型常量(public static final)。

String使用private final char value[]来实现字符串的存储,也就是说String对象创建之后,就不能再修改此对象中存储的字符串内容,就是因为如此,才说String类型是不可变的.

String对象比较:
单独使用""引号创建的字符串都是常量,编译期就已经确定存储到常量池中;
使用new String("")创建的对象会存储到堆内存中,是运行期新创建的;
使用只包含常量的字符串连接符如"aa" + "bb"创建的也是常量,编译期就能确定,已经确定存储到常量池中;
使用包含变量的字符串连接符如"aa" + s1创建的对象是运行期才创建的,存储在堆中;StringBuffer 与 StringBuilder对象则是可变的!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: