-
==
、equals
、hashcode
的区别1. ==
a. 基本类型:比较的是值是否相等 b. 引用类型(类、接口、数组):比较的是内存存放地址是否相同
补充:对象存放在堆中,栈中存放的是对象的引用地址。由此可见"=="是对栈中的值进行比较,如果要比较堆中对象的内容是否相同,则需要重写
equals
。2. equals
a. 默认情况:判断对象的内存地址引用是否相同,即判断是否为同一对象。 b. 重写对象equals方法:视方法实现而定。
3. hashCode
通过哈希算法(散列算法)计算返回一个hash码数值,用于对对象进行散列的时候作为key输入,为保证散列的存取性能,因此hash会尽可能不同。
作用:Java中集合有两类:List、Set。前者集合内元素是有序、可重复的;后者元素无序、不可重复。为保证元素不重复,采用哈希表的原理来计算判断。
当集合要添加新的元素时,先调用这个元素的
hashCode
方法,定位到它应该防止的物理位置上。该位置无元素时,则直接存储;该位置上已有元素,则需通过equals方法对比,为保证集合内元素唯一,所以比较相同则不存储。从而大大降低存储效率。 -
String
、StringBuffer
、StringBuilder
的区别Java语言中,有4个类对字符或者字符串进行操作(
Character
、String
、StringBuffer
、StringBuider
、StringTokenizer
),其中Character
用于单个字符操作,String
用于字符串操作,属于不可变类;而StringBuffer
也是用于字符串操作,但属于可变类。String
是不可变类,也就是说String
一旦被创建,其值将不能被改变,因此适合在需要被共享的场合中使用,如果用String
来保存一个经常被修改的字符串,在字符串被修改是会比StringBuffer
多很多附加操作,同时生成很多无用对象,从而会影响程序性能。当一个字符串经常需要被修改时,最好使用StringBuffer
来实现。StringBuilder
是可变类,与StringBuffer
类似,都是字符串缓冲区,但StringBuilder
是不是线程安全的,如果只是单线程中使用字符串缓冲区,那StringBuilder
效率更高些。当有多个线程访问时,最好使用线程安全的StringBuffer
。因为StringBuffer
必要时可以对这些方法进行同步,所以任意特定实例上的所有操作就好像是以串行顺序发生的,改顺序与所涉及的每个线程进行的方法调用顺序一致。
执行效率:StringBuilder
>StringBuffer
>String
-
数组与链表的区别
1. 数组的特点
1. 内存中为一块连续的区域 2. 需预留空间,使用前要先申请所占内存大小,因此可能会浪费存储空间 3. 插入数据和删除数据效率低。删除插入时都需大规模元素移动 4. 随机读取效率很高。因为数组是连续的,知道每一个数据的内存地址,可以直接找到该地址的数据 5. 不利于扩展,数组定义的空间不够时需重新定义数组
2. 链表的特点
1. 可以存在内存中任何地方,不要求连续 2. 每个数据都保存了下一个数据的内存地址,可以通过这个地址找到下一个数据 3. 增加删除数据很容易 4. 查找数据时效率低。因为不具有随机访问性,所以访问某个位置的数据都要从第一个数据开始访问,然后根据第一个数据保存的下一个数据地址找到第二个数据,必须从第一个人开始问起 5. 不指定大小,扩展方便
-
List
、Map
、Set
的区别List
和Set
是存储单列数据的集合,Map
是存储键值对这样的双列数据的集合。List
中数据有序、可重复。Map
中数据无序、键不可重复但值可重复。Set
中数据无序、不可重复,元素在集合中的位置由元素的hashCode
决定。List
接口实现类:1. LinkedList:基于链表实现,内存散列,增删快,查找慢。 2. ArrayList:基于数组实现,非线程安全,效率高,增删慢,查找快。 3. Vector:基于数组实现,线程安全,效率低,增删慢,查找慢。
Set
接口实现类:1. HashSet:用HashMap实现,不可重复,使用时需重写equals和hashCode 2. LinkedHashSet:继承自HashSet,同时基于LinkedHashMap来进行实现
Map
接口实现类:1. HashMap:基于哈希表的Map接口实现,非线程安全,高效,支持null值和null键 2. HashTable:线程安全,低效,不支持null值和null键 3. LinkedHashMap:继承自HashMap,保存了记录的插入顺序 4. SortMap接口:TreeMap,能够把保存的记录根据键值对排序,默认升序
-
Wait
和Sleep
区别Wait
用于线程间通信,当等待条件为真且线程被唤醒时他会释放锁。Sleep
释放CPU资源或者让当前线程停止执行一段时间,但不会释放锁。 -
Serializable
和Parcelable
将某个特定的对象保存到文件中,隔一段时间后再把它读取到内存中使用,那么该对象就需要实现序列化操作,在java可以使用Serializable接口实现对象的序列化,而在android中既可以使用Serializable、Parcelable实现对象序列化。但是内存操作是更倾向于实现Parcelable接口,这样传输效率更高。
序列化:
由于存在于内存中的对象都是暂时的,无法长期贮存,为了把对象的状态保存下来,这是需要把对象写入到磁盘或者其他介质中
反序列化:
把已存在磁盘或者其他介质中的对象,读取到内存中,以便后续操作
序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中,先将对象的公共字段和私有字段以及类的名称(包括类所在的程序集)转换成字节流,然后把字节流写入到数据流。在随后对对象进行反序列化时,将创建出与原对象完全相同的副本-
Serializable
该方式主要依靠ObjectInputStream
和ObjectOutputStream
实现序列化与反序列化,通过流对象把类对象写到文件中,并在需要时恢复对象。但是两者并不是同一个对象,反序列化后的对象是新创建的。该方式使用了反射,序列化过程较慢,在序列化的时候会创建许多临时对象,容易触发垃圾回收注:
1. 如果反序列类的成员变量的类型或者类名发生了变化,那么即使serialVersionUID相同也无法正常反序列化成功
2. 静态成员变量属于类不属于对象,不会参与序列化过程,使用transient关键字标记的成员变量也不会参与序列化过程 Parcelable
序列化过程,writeToParcel
方法实现序列化功能,其内部是通过Parcel的一系列write方法完成的,接着通过CREATOR内部对象来完成反序列化,其内部通过createFromParcel
方法来创建序列化对象并通过newArray
方法创建数组,最终利用Parcel的一系列read方法完成发序列化,最后由describeContents
完成内容描述功能,该方法一般返回0,仅当对象中存在文件描述符时返回1。
通过writeToParcel
将我们的对象映射成Parcel对象,再通过createFromParcel
将Parcel对象映射成我们的对象。这个过程需要自行实现且写的顺序和读的顺序必须一致。大致原理是将一个完整的对象进行分解,而分解后的每一部分都是Intent所支持的数据类型,这样就实现传递对象的功能了-
Parcelable
与Serializable
区别- 两者实现差异
Serializable
的实现,只需要实现该接口即可。这只是给对象打了个标记(UID),系统会自动将其序列化。而Parcelable
的实现,不仅需要实现该接口,还需要再累中添加一个静态成员变量CREATOR,这个变量需要实现Parcelable.Creator接口,并实现读写的抽象方法 - 两者设计初衷
Serializable
是为了序列化对象到本地文件、数据库、网络流、RMI以便数据传输,当然这种传输可以是程序内的也可以是程序间的。而Android的Parcelable
是由于Serializable
效率过低,消耗大,而android中数据传递主要是在内存环境中,因此Parcelable
的出现是为了满足数据在内存中低开销而且高效传递问题 - 两者效率选择
Parcelable
的性能比Serializable
好,在内存开销方面较小,所以Android应用程序在内存间数据传输时推荐使用Parcelable
,如activity间传输数据和AIDL数据传递,Serializable
将数据持久化的操作方便,因此在将对象序列化到存储设置中或将对象序列化后通过网络传输时建议选择Serializable
(Parcelable
也是可以的,只不过实现和操作过程太麻烦,并且为了防止Android版本不同而导致Parcelable
可能不同,因此在序列化到存储设备或者网络传输方面还是尽量选择Serializable
接口) - 两者注意点
两者执行反序列操作后的对象都是新创建的,内容一样但对象不同
- 两者实现差异
-
JAVA 知识
猜你喜欢
转载自blog.csdn.net/weixin_34192816/article/details/87256342
今日推荐
周排行