2022年Java知识总结 .pdf
《2022年Java知识总结 .pdf》由会员分享,可在线阅读,更多相关《2022年Java知识总结 .pdf(32页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、JAVA 中堆和栈的区别堆内存:用于存储局部变量,当数据使用完,所占空间会自动释放栈内存o数组和对象,通过new 建立的实例都放在堆内存中o每一个实体都有内存地址值o实体中的变量都有默认的初始值o实体不再被使用,会在不确定的时间被垃圾回收器回收方法区o本地方法,寄存器在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配。当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后, Java 会自动释放掉为该变量所分配的内存空间,该内存空间可以立即被另作他用。堆内存用来存放由new 创建的对象和数组。在堆中分配的内存,由Java 虚拟机的自动垃
2、圾回收器来管理。在堆中产生了一个数组或对象后,还可以在栈中定义一个特殊的变量,让栈中这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。引用变量就相当于是为数组或对象起的一个名称,以后就可以在程序中使用栈中的引用变量来访问堆中的数组或对象。java 中变量在内存中的分配1、类变量( static 修饰的变量):在程序加载时系统就为它在堆中开辟了内存,堆中的内存地址存放于栈以便于高速访问。静态变量的生命周期-一直持续到整个系统 关闭2、实例变量:当你使用java 关键字 new 的时候,系统在堆中开辟并不一定是连续的空间分配给变量 (比如说类实例),然后根据
3、零散的堆内存地址,通过哈希 算法 换算为一长串数字以表征这个变量在堆中的物理位置 。 实例变量的生命周期-当实例变量的引用丢失后,将被 GC (垃圾回收器)列入可回收“ 名单 ” 中,但并不是马上就释放堆中内存3、局部变量:局部变量,由声明在某方法,或某代码段里(比如for 循环),执行到它的时候在栈中开辟内存,当局部变量一但脱离作用域,内存立即释放附: java 的内存机制精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 1 页,共 32 页 - - - - - - - - - - Java 把内存划分成
4、两种:一种是栈内存,另一种是堆内存。在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配,当在一段代码块定义一个变量时,Java 就在栈中为这个变量分配内存空间,当超过变量的作用域后,Java 会自动释放掉为该变量分配的内存空间,该内存空间可以立即被另作它用。堆内存用来存放由new 创建的对象和数组,在堆中分配的内存,由 Java 虚拟机的自动垃圾回收器来管理。在堆中产生了一个数组或者对象之后,还可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,以后就可以在程序中使用栈中的引用变量来访问堆中的数组
5、或者对象, 引用变量就相当于是为数组或者对象起的一个名称。引用变量是普通的变量,定义时在栈中分配, 引用变量在程序运行到其作用域之外后被释放。而数组和对象本身在堆中分配,即使程序运行到使用new 产生数组或者对象的语句所在的代码块之外,数组和对象本身占据的内存不会被释放,数组和对象在没有引用变量指向它的时候,才变为垃圾, 不能在被使用,但仍然占据内存空间不放,在随后的一个不确定的时间被垃圾回收器收走(释放掉)。这也是Java 比较占内存的原因,实际上,栈中的变量指向堆内存中的变量,这就是Java 中的指针!优缺点 :栈的优势是, 存取速度比堆要快,仅次于直接位于CPU 中的寄存器。 但缺点是,
6、 存在栈中的数据大小与生存期必须是确定的,缺乏灵活性。另外,栈数据可以共享。堆的优势是可以动态地分配内存大小,生存期也不必事先告诉编译器,Java 的垃圾收集器会自动收走这些不再使用的数据。但缺点是,由于要在运行时动态分配内存,存取速度较慢。java 集合类说明与区别1ArrayList: 元素单个,效率高,多用于查询2Vector: 元素单个,线程安全,多用于查询3LinkedList: 元素单个,多用于插入和删除4HashMap: 元素成对,元素可为空5HashTable: 元素成对,线程安全,元素不可为空集合类说明及区别Collection 精品资料 - - - 欢迎下载 - - - -
7、 - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 2 页,共 32 页 - - - - - - - - - - List LinkedList ArrayList Vector Stack SetMap Hashtable HashMap WeakHashMapCollection接口Collection是最基本的集合接口,一个Collection代表一组Object ,即 Collection的元素( Elements )。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。 Java SDK 不提供直接继承自Collecti
8、on的类, Java SDK 提供的类都是继承自Collection的“ 子接口 ” 如 List 和 Set。所有实现 Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection , 有一个Collection参数的构造函数用于创建一个新的Collection ,这个新的 Collection与传入的 Collection有相同的元素。后一个构造函数允许用户复制一个 Collection 。如何遍历 Collection中的每一个元素?不论Collection的实际类型如何, 它都支持一个iterator()的方法, 该方法返回一个迭代子,
9、使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:Iterator it = collection.iterator(); / 获得一个迭代子while(it.hasNext() Object obj = it.next(); / 得到下一个元素 由 Collection接口派生的两个接口是List 和 Set。List接口List 是有序的Collection ,使用此接口能够精确的控制每个元素插入的位置。用户能够使用索引(元素在List 中的位置,类似于数组下标)来访问List 中的元素,这类似于Java的数组。和下面要提到的Set 不同, List 允许有相同的元
10、素。除了具有 Collection接口必备的iterator()方法外, List 还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比, ListIterator多了一些add() 之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。实现 List 接口的常用类有LinkedList,ArrayList ,Vector 和 Stack 。LinkedList类LinkedList实现了 List 接口,允许 null 元素。 此外 LinkedList提供额外的get, remove ,insert 方法在LinkedLis
11、t的首部或尾部。这些操作使LinkedList可被用作堆栈(stack ),队列( queue )或双向队列(deque )。注意 LinkedList没有同步方法。如果多个线程同时访问一个List ,则必须自己实现访问同步。一种解决方法是在创建List 时构造一个同步的List :List list = Collections.synchronizedList(new LinkedList(.); 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 3 页,共 32 页 - - - - - - - - -
12、- ArrayList类ArrayList实现了可变大小的数组。它允许所有元素,包括null 。ArrayList没有同步。size,isEmpty ,get,set 方法运行时间为常数。但是add 方法开销为分摊的常数,添加n个元素需要O(n) 的时间。其他的方法运行时间为线性。每个 ArrayList实例都有一个容量(Capacity ),即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。和 LinkedList一样, ArrayLi
13、st也是非同步的(unsynchronized)。Vector类Vector 非常类似 ArrayList ,但是 Vector 是同步的。 由 Vector 创建的 Iterator ,虽然和ArrayList创建的 Iterator是同一接口,但是,因为Vector 是同步的,当一个Iterator被创建而且正在被使用,另一个线程改变了Vector 的状态(例如,添加或删除了一些元素),这时调用 Iterator的方法时将抛出ConcurrentModificationException,因此必须捕获该异常。在考虑并发的情况下用Vector (保证线程的安全)。在不考虑并发的情况下用Arr
14、ayList (不能保证线程的安全)Stack 类Stack 继承自 Vector , 实现一个后进先出的堆栈。Stack 提供 5 个额外的方法使得Vector得以被当作堆栈使用。基本的push 和 pop 方法,还有peek 方法得到栈顶的元素,empty方法测试堆栈是否为空, search 方法检测一个元素在堆栈中的位置。Stack 刚创建后是空栈。2 , Set 接口Set 具有与Collection 完全一样的接口, 因此没有任何额外的功能,不像前面有几个不同的List 。实际上Set 就是Collection ,只是行为不同。 (这是继承与多态思想的典型应用:表现不同的行为) 。
15、其次, Set 是一种不包含重复的元素的Collection , 加入 Set 的元素必须定义equals() 方法以确保对象的唯一性( 即任意的两个元素e1 和 e2 都有e1.equals(e2)=false ) ,与 List 不同的是,Set 接口不保证维护元素的次序。最后,Set 最多有一个null 元素。很明显,Set 的构造函数有一个约束条件,传入的Collection 参数不能包含重复的元素。请注意:必须小心操作可变对象(Mutable Object ) 。如果一个Set 中的可变元素改变了自身状态导致Object.equals(Object)=true 将导致一些问题。Has
16、hSet 类为快速查找设计的Set 。存入HashSet 的对象必须定义hashCode() 。LinkedHashSet 类:具有HashSet 的查询速度,且内部使用链表维护元素的顺序( 插入的次序) 。于是在使用迭代器遍历Set 时,结果会按元素插入的次序显示。精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 4 页,共 32 页 - - - - - - - - - - TreeSet 类保存次序的Set, 底层为树结构。使用它可以从Set 中提取有序的序列。Map接口请注意, Map 没有继承 Co
17、llection接口, Map 提供 key 到 value 的映射。一个Map 中不能包含相同的key,每个 key 只能映射一个value 。Map 接口提供3 种集合的视图, Map的内容可以被当作一组key 集合,一组value 集合,或者一组key-value 映射。Hashtable类Hashtable继承 Map 接口,实现一个key-value 映射的哈希表。任何非空(non-null)的对象都可作为key 或者 value 。添加数据使用put(key, value),取出数据使用get(key) ,这两个基本操作的时间开销为常数。Hashtable通过 initial ca
18、pacity和 load factor两个参数调整性能。通常缺省的load factor 0.75 较好地实现了时间和空间的均衡。增大load factor可以节省空间但相应的查找时间将增大,这会影响像get 和 put 这样的操作。由于作为 key 的对象将通过计算其散列函数来确定与之对应的value 的位置,因此任何作为 key 的对象都必须实现hashCode 和 equals 方 法。 hashCode 和 equals 方法继承自根类 Object ,如果你用自定义的类当作key 的话,要相当小心,按照散列函数的定义,如果两个对象相同,即 obj1.equals(obj2)=true
19、,则它们的hashCode 必须相同,但如果两个对象不同,则它们的hashCode 不一定不同,如果两个不同对象的hashCode 相同,这种现象称为冲突, 冲突会导致操作哈希表的时间开销增大,所以尽量定义好的hashCode() 方法,能加快哈希表的操作。如果相同的对象有不同的hashCode ,对哈希表的操作会出现意想不到的结果(期待的get 方法返回 null ) , 要避免这种问题, 只需要牢记一条: 要同时复写equals 方法和 hashCode方法,而不要只写其中一个。Hashtable是同步的。HashMap类HashMap和 Hashtable类似,不同之处在于HashMap
20、是非同步的,并且允许null ,即 null value和 null key 。,但是将HashMap视为 Collection时( values() 方法可返回Collection ),其迭代子操作时间开销和HashMap 的容量成比例。因此,如果迭代操作的性能相当重要的话,不要将HashMap的初始化容量设得过高,或者load factor过低。WeakHashMap类WeakHashMap是一种改进的HashMap ,它对 key 实行 “ 弱引用 ” ,如果一个key 不再被外部所引用,那么该key 可以被 GC 回收。总结如果涉及到堆栈,队列等操作,应该考虑用List ,对于需要快速
21、插入,删除元素,应该使用 LinkedList,如果需要快速随机访问元素,应该使用ArrayList 。如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高,如果多个线程可能同时操作一个类,应该使用同步的类。要特别注意对哈希表的操作,作为key 的对象要正确复写equals 和 hashCode 方法。尽量返回接口而非实际的类型,如返回List 而非 ArrayList ,这样如果以后需要将ArrayList换成 LinkedList时,客户端代码不用改变。这就是针对抽象编程。精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师
22、归纳 - - - - - - - - - -第 5 页,共 32 页 - - - - - - - - - - 同步性Vector 是同步的。 这个类中的一些方法保证了Vector 中的对象是线程安全的。而 ArrayList则是异步的,因此ArrayList中的对象并不是线程安全的。因为同步的要求会影响执行的效率,所以如果你不需要线程安全的集合那么使用ArrayList是一个很好的选择,这样可以避免由于同步带来的不必要的性能开销。数据增长从内部实现机制来讲ArrayList和 Vector 都是使用数组(Array) 来控制集合中的对象。当你向这两种类型中增加元素的时候,如果元素的数目超出了内
23、部数组目前的长度它们都需要扩展内部数组的长度,Vector 缺省情况下自动增长原来一倍的数组长度,ArrayList是原来的 50%,所以最后你获得的这个集合所占的空间总是比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector 有一些优势, 因为你可以通过设置集合的初始化大小来避免不必要的资源开销。使用模式在 ArrayList和 Vector 中,从一个指定的位置(通过索引)查找数据或是在集合的末尾增加、移除一个元素所花费的时间是一样的,这个时间我们用O(1) 表示。但是,如果在集合的其他位置增加或移除元素那么花费的时间会呈线形增长:O(n-i) ,其中 n 代表集合中元
24、素的个数, i 代表元素增加或移除元素的索引位置。 为什么会这样呢?以为在进行上述操作的时候集合中第i 和第 i 个元素之后的所有元素都要执行位移的操作。这一切意味着什么呢?这意味着, 你只是查找特定位置的元素或只在集合的末端增加、移除元素, 那么使用 Vector或 ArrayList都可以。如果是其他操作,你最好选择其他的集合操作类。比如,LinkList集合类在增加或移除集合中任何位置的元素所花费的时间都是一样的?O(1),但它在索引一个元素的使用缺比较慢 O(i), 其中 i 是索引的位置.使用 ArrayList也很容易,因为你可以简单的使用索引来代替创建iterator对象的操作。
25、LinkList也 会为每个插入的元素创建对象,所有你要明白它也会带来额外的开销。最后,建议使用一个简单的数组(Array )来代替Vector 或 ArrayList 。尤其是对于执行效率要求高的程序更应如此。因为使用数组(Array) 避免了同步、额外的方法调用和不必要的重新分配空间的操作。相互区别Vector和 ArrayList1,vector 是线程同步的,所以它也是线程安全的,而ArrayList是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用ArrayList效率比较高。2,如果集合中的元素的数目大于目前集合数组的长度时,vector 增长率为目前数组长度的100%,
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 2022年Java知识总结 2022 Java 知识 总结
限制150内