21. TreeMap、HashMap、LindedHashMap的区别
- LinkedHashMap可以保证HashMap集合有序,存入的顺序和取出的顺序一致。
- TreeMap实现SortMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。
- HashMap不保证顺序,即为无序的,具有很快的访问速度。HashMap最多只允许一条记录的键为Null;允许多条记录的值为 Null。HashMap不支持线程的同步。
我们在开发的过程中使用HashMap比较多,在Map中在Map 中插入、删除和定位元素,HashMap 是最好的选择。
如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列。
22. Collection包结构,与Collections的区别 - Collection 是集合类的上级接口,子接口主要有Set、List 、Map。
- Collecions 是针对集合类的一个帮助类, 提供了操作集合的工具方法,一系列静态方法实现对各种集合的搜索、排序线性、线程安全化等操作。
例如
Map<String, Object> map4 = Collections.synchronizedMap(new HashMap<String,
Object>()); 线程安全 的HashMap
Collections.sort(List<T> list, Comparator<? super T> c); 排序 List
Collection
Collection 是单列集合
List元素是有序的、可重复。
有序的 collection,可以对列表中每个元素的插入位置进行精确地控制。可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。可存放重复元素,元素存取是有序的。
List接口中常用类
Vector:线程安全,但速度慢,已被ArrayList替代。底层数据结构是数组结构。
ArrayList:线程不安全,查询速度快。底层数据结构是数组结构。
LinkedList:线程不安全。增删速度快。底层数据结构是列表结构。
Set接口中常用的类
Set(集) 元素无序的、不可重复。
取出元素的方法只有迭代器。不可以存放重复元素,元素存取是无序的。
HashSet:线程不安全,存取速度快。它是如何保证元素唯一性的呢?依赖的是元素的hashCode方法和euqals方法。
TreeSet:线程不安全,可以对Set集合中的元素进行排序。它的排序是如何进行的:通过compareTo或者compare方法中的来保证元素的唯一性。元素是以二叉树的形式存放的。
Map一个双列集合
Hashtable:线程安全,速度快。底层是哈希表数据结构。是同步的。不允许null作为键,null作为值。
Properties:用于配置文件的定义和操作,使用频率非常高,同时键和值都是字符串。是集合中可以和IO技术相结合的对象。
HashMap:线程不安全,速度慢。底层也是哈希表数据结构。是不同步的。允许null作为键,null作为值,替代了Hashtable。
LinkedHashMap: 可以保证HashMap集合有序。存入的顺序和取出的顺序一致。
TreeMap:可以用来对Map集合中的键进行排序
23. try、catch、finally,try里有return,finally还执行吗?
肯定会执行finally{}块的代码。只有在try{}块中包含遇到System.exit(0)之类的导致Java虚拟机直接退出的语句才会不执行。
当程序执行try{}遇到return时,程序会先执行return语句,但并不会立即返回——也就是把return语句要做的一切事情都准备好,也就是在将要返回、但并未返回的时候,程序把执行流程转去执行finally块,当finally块执行完成后就直接返回刚才return语句已经准备好的结果。
24. Excption与Error包结构。OOM、SOF遇到过哪些情况,遇到过哪些情况?
Throwable是 Java 语言中所有错误或异常的超类。
Throwable包含两个子类: Error 和 Exception 。它们通常用于指示发生了异常情况。
Throwable包含了其线程创建时线程执行堆栈的快照,它提供了printStackTrace()等接口用于获取堆栈跟踪数据等信息。
Java将可抛出(Throwable)的结构分为三种类型:
被检查的异常(Checked Exception)、运行时异常(RuntimeException)、错误(Error)。
运行时异常RuntimeException
定义 : RuntimeException及其子类都被称为运行时异常。
特点 : Java编译器不会检查它 也就是说,当程序中可能出现这类异常时,倘若既"没有通过throws声明抛出它",也"没有用try-catch语句捕获它",还是会编译通过。
- 堆内存溢出 OutOfMemoryError(OOM)
除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能。
Java Heap 溢出:
一般的异常信息:java.lang.OutOfMemoryError:Java heap spacess。
java堆用于存储对象实例,我们只要不断的创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,就会在对象数量达到最大堆容量限制后产生内存溢出异常。 - 堆栈溢出 StackOverflow (SOF)
StackOverflowError 的定义:
当应用程序递归太深而发生堆栈溢出时,抛出该错误。因为栈一般默认为1-2m,一旦出现死循环或者是大量的递归调用,在不断的压栈过程中,造成栈容量超过1m而导致溢出。
栈溢出的原因:
1)递归调用。
2)大量循环或死循环。
3)全局变量是否过多。
4)数组、List、map数据过大。
25. Java(OOP)面向对象的三个特征与含义
封装(高内聚低耦合 -->解耦) - 封装是指将某事物的属性和行为包装到对象中,这个对象只对外公布需要公开的属性和行为,而这个公布也是可以有选择性的公布给其它对象。在java中能使用private、protected、public三种修饰符或不用(即默认defalut)对外部对象访问该对象的属性和行为进行限制。
- java的继承(重用父类的代码)
继承是子对象可以继承父对象的属性和行为,亦即父对象拥有的属性和行为,其子对象也就拥有了这些属性和行为。 - java中的多态(父类引用指向子类对象)
多态是指父对象中的同一个行为能在其多个子对象中有不同的表现。
有两种多态的机制:编译时多态、运行时多态。
1)方法的重载:重载是指同一类中有多个同名的方法,但这些方法有着不同的参数。,因此在编译时就可以确定到底调用哪个方法,它是一种编译时多态。
2)方法的重写:子类可以覆盖父类的方法,因此同样的方法会在父类中与子类中有着不同的表现形式。
26. Override和Overload的含义去区别 - 重载 Overload方法名相同,参数列表不同(个数、顺序、类型不同)与返回类型无关。
- 重写 Override 覆盖。 将父类的方法覆盖。
重写方法重写:方法名相同,访问修饰符只能大于被重写的方法访问修饰符,方法签名个数,顺序个数类型相同。 - Override(重写)
方法名、参数、返回值相同。
子类方法不能缩小父类方法的访问权限。
子类方法不能抛出比父类方法更多的异常(但子类方法可以不抛出异常)。
存在于父类和子类之间。
方法被定义为final不能被重写。 - Overload(重载)
参数类型、个数、顺序至少有一个不相同。
不能重载只有返回值不同的方法名。
存在于父类和子类、同类中。
而重载的规则
1)必须具有不同的参数列表。
2)可以有不同的返回类型,只要参数列表不同就可以了。
3)可以有不同的访问修饰符。
4)可以抛出不同的异常。
重写方法的规则
1)参数列表必须完全与被重写的方法相同,否则不能称其为重写而是重载。
2)返回的类型必须一直与被重写的方法的返回类型相同,否则不能称其为重写而是重载。
3)访问修饰符的限制一定要大于被重写方法的访问修饰符(public>protected>default>private)。
4)重写方法一定不能抛出新的检查异常或者比被重写方法申明更加宽泛的检查型异常。
27. Interface与abstract类的区别
Interface 只能有成员常量,只能是方法的声明。
Abstract class可以有成员变量,可以声明普通方法和抽象方法。
interface是接口,所有的方法都是抽象方法,成员变量是默认的public static final 类型。接口不能实例化自己。
abstract class是抽象类,至少包含一个抽象方法的累叫抽象类,抽象类不能被自身实例化,并用abstract关键字来修饰。
28. Static?class?与non?static?class的区别 - static class(内部静态类)
1)用static修饰的是内部类,此时这个内部类变为静态内部类;对测试有用。
2)内部静态类不需要有指向外部类的引用。
3)静态类只能访问外部类的静态成员,不能访问外部类的非静态成员。 - non static class(非静态内部类)
1)非静态内部类需要持有对外部类的引用。
2)非静态内部类能够访问外部类的静态和非静态成员。
3)一个非静态内部类不能脱离外部类实体被创建。
4)一个非静态内部类可以访问外部类的数据和方法。
29. foreach与正常for循环效率对比
用for循环arrayList 10万次花费时间:5毫秒。
用foreach循环arrayList 10万次花费时间:7毫秒。
用for循环linkList 10万次花费时间:4481毫秒。
用foreach循环linkList 10万次花费时间:5毫秒。
循环ArrayList时,普通for循环比foreach循环花费的时间要少一点。
循环LinkList时,普通for循环比foreach循环花费的时间要多很多。 - ArrayList:ArrayList是采用数组的形式保存对象的,这种方式将对象放在连续的内存块中,所以插入和删除时比较麻烦,查询比较方便。
- LinkList:LinkList是将对象放在独立的空间中,而且每个空间中还保存下一个空间的索引,也就是数据结构中的链表结构,插入和删除比较方便,但是查找很麻烦,要从第一个开始遍历。
结论:
需要循环数组结构的数据时,建议使用普通for循环,因为for循环采用下标访问,对于数组结构的数据来说,采用下标访问比较好。
需要循环链表结构的数据时,一定不要使用普通for循环,这种做法很糟糕,数据量大的时候有可能会导致系统崩溃。
30. IO与NIO
NIO是为了弥补IO操作的不足而诞生的,NIO的一些新特性有:非阻塞I/O,选择器,缓冲以及管道。管道(Channel),缓冲(Buffer) ,选择器( Selector)是其主要特征。
概念解释
Channel——管道实际上就像传统IO中的流,到任何目的地(或来自任何地方)的所有数据都必须通过一个 Channel 对象。一个 Buffer 实质上是一个容器对象。
每一种基本 Java 类型都有一种缓冲区类型:
ByteBuffer——byte
CharBuffer——char
ShortBuffer——short
IntBuffer——int
LongBuffer——long
FloatBuffer——float
DoubleBuffer——double
Selector——选择器用于监听多个管道的事件,使用传统的阻塞IO时我们可以方便的知道什么时候可以进行读写,而使用非阻塞通道,我们需要一些方法来知道什么时候通道准备好了,选择器正是为这个需要而诞生的。
NIO和传统的IO有什么区别呢?
IO是面向流的,NIO是面向块(缓冲区)的。
IO面向流的操作一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。,导致了数据的读取和写入效率不佳。
NIO面向块的操作在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多,同时数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。通俗来说,NIO采取了“预读”的方式,当你读取某一部分数据时,他就会猜测你下一步可能会读取的数据而预先缓冲下来。
IO是阻塞的,NIO是非阻塞的
对于传统的IO,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。
而对于NIO,使用一个线程发送读取数据请求,没有得到响应之前,线程是空闲的,此时线程可以去执行别的任务,而不是像IO中那样只能等待响应完成。
NIO和IO适用场景
NIO是为弥补传统IO的不足而诞生的,但是尺有所短寸有所长,NIO也有缺点,因为NIO是面向缓冲区的操作,每一次的数据处理都是对缓冲区进行的,那么就会有一个问题,在数据处理之前必须要判断缓冲区的数据是否完整或者已经读取完毕,如果没有,假设数据只读取了一部分,那么对不完整的数据处理没有任何意义。所以每次数据处理之前都要检测缓冲区数据。
那么NIO和IO各适用的场景是什么呢?
如果需要管理同时打开的成千上万个连接,这些连接每次只是发送少量的数据,例如聊天服务器,这时候用NIO处理数据可能是个很好的选择。
而如果只有少量的连接,而这些连接每次要发送大量的数据,这时候传统的IO更合适。使用哪种处理数据,需要在数据的响应等待时间和检查缓冲区数据的时间上作比较来权衡选择。
码巢对标阿里P6
更多学习资料获取,请扫码进群或关注我们的公众号


这篇博客详细介绍了Java中的HashMap、TreeMap、LindedHashMap的区别,强调了它们在有序性、性能和线程安全性上的特性。此外,还探讨了Collection和Collections接口的区别,以及在不同场景下的使用选择。同时,文章涵盖了面试中常见的Java异常处理、集合类结构、OOP特性、接口与抽象类的对比,以及IO与NIO的差异和适用场景。对于准备Java面试,尤其是BAT级别的职位,这些都是重要的知识点。
4967

被折叠的 条评论
为什么被折叠?



