Skip to content

Commit b3a3640

Browse files
committed
list
1 parent 07051a5 commit b3a3640

11 files changed

Lines changed: 277 additions & 40 deletions

File tree

src/com/yale/test/java/fanxing/Message.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ public static void main(String[] args) {
108108
*
109109
* Java所强调的兼容性是"二进制向后兼容性(binary backwards compatibility)"二进制兼容性并不等于源码兼容性,class文件就是java程序的二进制表现
110110
* 这句话的意思是说,你用jdk1编译出来的class文件,放在jdk8的JVM里面一样可以运行.但是你基于jdk1写的java代码并不一定可以在jdk8的上面一定编译通过,不是源码兼容的.
111-
*
111+
* 比如说,你最早的源码里面使用了enum这个关键字作为变量,之前编译成class文件了,这个class文件是可以在JVM里面运行的,但你java代码在jdk8上编译不通过了
112112
* raw type 这个概念怎么来的?
113113
* 还有用java.util.List为例,在原地泛型化后,现在这个类型变成了java.util.ArrayList<E>。但是以前的代码直接用ArrayList,在新版本里必须还能继续用,
114114
* 所以就引出了“raw type”的概念,—— 一个类型虽然被泛型化了,但还可以把它当作非泛型化的类型用。

src/com/yale/test/math/array/CollectionDemo.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* public interface Collection<E> extends Iterable<E>
1111
* List(允许重复),Set(不允许重复)
1212
* List有三个非常重要的子类:ArrayList,Vector,LinkedList
13+
* Set有俩个常用子类:HashSet(不允许重复,无序存储),TreeSet(不允许重复,有序存储)
1314
* @author dell
1415
*/
1516
public class CollectionDemo {

src/com/yale/test/thread/heima/zhangxiaoxiang/HashSetTest.java renamed to src/com/yale/test/math/array/HashSetTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.yale.test.thread.heima.zhangxiaoxiang;
1+
package com.yale.test.math.array;
22

33
import java.util.Collections;
44
import java.util.HashMap;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package com.yale.test.math.array;
2+
3+
import java.util.ArrayList;
4+
import java.util.Enumeration;
5+
import java.util.Iterator;
6+
import java.util.List;
7+
import java.util.ListIterator;
8+
import java.util.Vector;
9+
10+
public class IteratorDemo {
11+
public static void main(String[] args) {
12+
List<String> list = new ArrayList<String>();
13+
list.add("Hello");
14+
list.add("1");
15+
list.add("Hello");
16+
list.add("Word");
17+
Iterator<String> it = list.iterator();//集合输出就用Iterator,死记就行,方便
18+
int i =0;
19+
while(it.hasNext()) {//while循环实际上的意思是:不知道循环次数,但知道循环结束条件,就用while循环
20+
i ++;
21+
if (i==1) {
22+
/**
23+
* list在循环中如果增加数据会报错
24+
* java.util.ConcurrentModificationException
25+
* 而且Iterator没有增加方法,ListIterator才有增加方法
26+
*/
27+
//list.add("ListIterator可以在迭代过程中增加数据");
28+
}
29+
System.out.println(it.next());
30+
}
31+
32+
/**
33+
* list这个forEach怎么用?
34+
*/
35+
list.forEach(action);
36+
37+
ListIterator<String> listIt = list.listIterator();
38+
/**
39+
* 如果要想实现由后向前的输出,那么应该首先由前向后输出,否则无法实现双向,
40+
* 因为你向前向后靠的是指针,指针不指到后面,无法实现
41+
*/
42+
System.out.println("由后向前输入");
43+
while (listIt.hasPrevious()) {
44+
System.out.print(listIt.previous() + ",");
45+
}
46+
47+
/**
48+
* ListIterator 只有list接口才有,ListIterator是双向迭代接口
49+
*/
50+
51+
System.out.println("由前向后输入");
52+
i =0;
53+
while (listIt.hasNext()) {
54+
i ++;
55+
if (i==1) {
56+
listIt.add("ListIterator可以在迭代过程中增加数据");
57+
}
58+
System.out.print(listIt.next() + ",");
59+
}
60+
System.out.println();
61+
62+
/**
63+
* 如果要想实现由后向前的输出,那么应该首先由前向后输出,否则无法实现双向,
64+
* 因为你向前向后靠的是指针,指针不指到后面,无法实现
65+
*/
66+
System.out.println("由后向前输入");
67+
while (listIt.hasPrevious()) {
68+
System.out.print(listIt.previous() + ",");
69+
}
70+
71+
System.out.println();
72+
/**
73+
* Enumeration枚举输出,只有Vector支持枚举输出
74+
*/
75+
Vector<String> vector = new Vector<String>();
76+
vector.add("Hello");
77+
vector.add("1");
78+
vector.add("Hello");
79+
vector.add("Word");
80+
Enumeration<String> enumeration = vector.elements();
81+
while (enumeration.hasMoreElements()) {
82+
System.out.println("Enumeration枚举输出:" + enumeration.nextElement());
83+
}
84+
85+
for (Enumeration<String> e = vector.elements(); e.hasMoreElements();) {
86+
System.out.println("使用for循环进行枚举输出:" + e.nextElement());
87+
}
88+
}
89+
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
package com.yale.test.math.array;
2+
3+
import java.util.HashMap;
4+
import java.util.HashSet;
5+
import java.util.Set;
6+
import java.util.TreeSet;
7+
8+
class PersonSec implements Comparable<PersonSec> {
9+
private String name;
10+
private Integer age;
11+
12+
public PersonSec(String name, Integer age) {
13+
super();
14+
this.name = name;
15+
this.age = age;
16+
}
17+
public String getName() {
18+
return name;
19+
}
20+
public void setName(String name) {
21+
this.name = name;
22+
}
23+
public Integer getAge() {
24+
return age;
25+
}
26+
public void setAge(Integer age) {
27+
this.age = age;
28+
}
29+
@Override
30+
public String toString() {
31+
return "name=" + this.name + ",aget = " + this.age + "\n";
32+
}
33+
@Override
34+
public int compareTo(PersonSec o) {
35+
if (this.age > o.getAge()) {
36+
return 1;
37+
} else if(this.age < o.getAge()) {
38+
return -1;
39+
} else {
40+
return this.name.compareTo(o.getName());
41+
}
42+
}
43+
44+
/**
45+
* 这里的HashCode是用eclipse自动生成的方法
46+
*/
47+
@Override
48+
public int hashCode() {
49+
final int prime = 31;
50+
int result = 1;
51+
result = prime * result + ((age == null) ? 0 : age.hashCode());
52+
result = prime * result + ((name == null) ? 0 : name.hashCode());
53+
return result;
54+
}
55+
@Override
56+
public boolean equals(Object obj) {
57+
if (this == obj)
58+
return true;
59+
if (obj == null)
60+
return false;
61+
if (getClass() != obj.getClass())
62+
return false;
63+
PersonSec other = (PersonSec) obj;
64+
if (age == null) {
65+
if (other.age != null)
66+
return false;
67+
} else if (!age.equals(other.age))
68+
return false;
69+
if (name == null) {
70+
if (other.name != null)
71+
return false;
72+
} else if (!name.equals(other.name))
73+
return false;
74+
return true;
75+
}
76+
}
77+
/**
78+
* public interface Collection<E> extends Iterable<E>
79+
* List(允许重复),Set(不允许重复)
80+
* List有三个非常重要的子类:ArrayList,Vector,LinkedList
81+
* Set有俩个常用子类:HashSet(不允许重复,无序存储),TreeSet(不允许重复,升序存储)
82+
* @author dell
83+
*/
84+
public class SetDemo {
85+
public static void main(String[] args) {
86+
Set<String> set = new HashSet<String>();
87+
set.add("C");
88+
set.add("C");
89+
set.add("A");//重复元素
90+
set.add("D");//无序存储
91+
set.add("B");//无序存储
92+
93+
System.out.println(set);
94+
95+
Set<String> treeSet = new TreeSet<String>();
96+
treeSet.add("C");
97+
treeSet.add("C");
98+
treeSet.add("D");//重复元素
99+
treeSet.add("A");//升序存储
100+
treeSet.add("B");//无序存储
101+
System.out.println(treeSet);
102+
103+
104+
/**
105+
* TreeSet要求PersonSec类里面是所有属性都参与比较,否则比较会不准确
106+
* 否则TreeSet就会认为name名字一样的就是同一个类了,就会去重.换句话说TreeSet判断重复元素是依靠Comparable接口来完成的
107+
* TreeSet内部是一个TreeMap,HashSet是部是一个HashMap
108+
*/
109+
Set<PersonSec> treePerson = new TreeSet<PersonSec>();
110+
treePerson.add(new PersonSec("张三", 20));
111+
treePerson.add(new PersonSec("张三", 20));
112+
treePerson.add(new PersonSec("李四", 20));
113+
treePerson.add(new PersonSec("王五", 19));
114+
System.out.println("TreeSet要求所有属性都必须参与比较:" + treePerson);
115+
116+
/**
117+
* HashSet是利用equals和hashCode这俩个方法来判断重复的
118+
* 俩个方法都返回true才认为是同一个对象
119+
*/
120+
Set<PersonSec> hashSetPerson = new HashSet<PersonSec>();
121+
hashSetPerson.add(new PersonSec("张三", 20));
122+
hashSetPerson.add(new PersonSec("张三", 20));
123+
hashSetPerson.add(new PersonSec("李四", 20));
124+
hashSetPerson.add(new PersonSec("王五", 19));
125+
System.out.println("HashSet是利用equals和hashCode这俩个方法来判断重复的:" + hashSetPerson);
126+
127+
128+
PersonSec stu = new PersonSec("HashSet测试引用", 20);
129+
stu.setAge(12);
130+
HashMap<String, PersonSec> hashMap = new HashMap<String, PersonSec>();
131+
hashMap.put("yy", stu);
132+
133+
stu = new PersonSec("HashSet测试引用", 99);
134+
stu.setAge(20);
135+
136+
PersonSec sd = hashMap.get("yy");
137+
System.out.println("hashSet内部有自己的引用:" + sd.getAge());
138+
139+
//其实HashSet内部实现就是一个HashMap,只用了HashMap的键值
140+
HashSet sdf = new HashSet();
141+
sdf.add(1);
142+
143+
}
144+
}

src/com/yale/test/mldn/StringBufferDemo.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@
66
*/
77
public class StringBufferDemo {
88
public static void main(String[] args) {
9+
String str01 = "abc";
10+
String str02 = "abc";
11+
System.out.println("这俩个String对象实际上同一个:" + (str01 == str02));
12+
13+
914
/**
1015
* String,StringBuffer,StringBuilder这三个类都实现了CharSequence接口
1116
* StringBuffer是从jdk1.0出现的,StringBuffer的每个方法都有synchronized修饰,所以速度慢

src/com/yale/test/other/Stu.java

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/com/yale/test/run/Heap.png

118 KB
Loading

src/com/yale/test/run/JMM.png

77 KB
Loading

src/com/yale/test/run/JVMInfoTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,40 @@
1414
/**
1515
* http://blog.sina.com.cn/s/blog_c42004c90102w5ya.html
1616
* JVM 信息获取 之 ManagementFactory
17+
* https://yq.aliyun.com/articles/617782?spm=a2c4e.11153940.0.0.5a0f5491IqPiKQ&type=2
18+
* https://yq.aliyun.com/articles/622667?spm=a2c4e.11155435.0.0.a53a7229tBmQD4
19+
* https://blog.csdn.net/xtayfjpk/article/details/41924283
20+
* JVM内存模型:java堆,java栈(即虚拟机栈),本地方法栈,方法区和程序计数器。其中方法区和堆区是线程共享的,虚拟机栈,本地方法栈和程序计数器是线程私有的,也称线程隔离的,
21+
* 每个区域存储不同的内容。这2个知识点必须牢记,是掌握JVM内存模型的基础。
22+
* 程序计数:
23+
* JVM中的程序计数器是一块很小的内存区域,但是这块内存区域挺有意思的。主要特性有3个:
24+
1、存储内容:对于java普通方法(即没用native关键字修饰的方法),存储的是执行过程中当前指令的地址,而对于native方法,这里是空的(undefined),为啥呢?因为调用本地方法的时候可能已经超出了JVM虚拟机的内存地址了。
25+
2、线程私有的:为什么程序计数器是线程私有的?根据存储内容也好理解,假如是线程共享的,那多个线程执行的时候,都不知道自己当前线程执行的地址是哪个了,有的线程快,有的线程慢,快的执行完就进入下一步,等慢的线程执行完回来发现自己的地址都变了,岂不乱套?
26+
3、是JVM中唯一不会报内存溢出(OutOfMemoryError)的区域。
27+
* 虚拟机栈:
28+
* 虚拟机栈主要存储的是一个个栈帧,每个栈帧中存储的是局部变量表,操作数栈,动态链接和方法出口信息等。其中局部变量表中存储的是方法中定义的一些局部变量,
29+
* 对象的引用,参数,和方法的返回地址等。局部变量表所占用的空间大小在编译期就能确定,在方法运行的时候,并不会改变局部变量表的空间大小,这结合局部变量表
30+
* 存储的内容就很好理解。操作数栈可以理解为对当前操作的数据入出栈,对于64位长度的long和double类型,每个操作数占用2个字宽(slot),其他类型的操
31+
* 作数占用一个字宽(slot)。每个方法调用时都会创建一个栈帧,执行的过程对应的就是一个栈帧在虚拟机栈中从入栈到出栈的过程。有关栈帧的内容可以参考一个网友
32+
* 写的一篇博客:https://blog.csdn.net/xtayfjpk/article/details/41924283,讲的很好很详细。这里放个栈帧的图,看了一目了然
33+
* 关于虚拟机栈内存溢出有2种情况:
34+
1、线程请求的栈深度 超过了虚拟机允许的深度,会抛出StackOverflowError,所以当我们在代码中看到这个异常时,就应该想到可能是虚拟机栈出了问题。
35+
2、如果虚拟机栈可以动态扩展(当前大部分JVM都可以动态扩展,不过JVM也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时,会抛出OutOfMemoryError异常。
36+
* 本地方法栈
37+
这块知识点比较简单,本地方法栈和虚拟机栈的功能类似,只不过是为JVM调用native方法时服务的,而且JVM对本地方法使用的语言(比如Java调用C语言实
38+
现的功能,就需要定义native方法来实现)、使用方式和数据结构都没有强制规定,因此不同的虚拟机可以自由实现。而且HotSpot虚拟机直接把本地方法栈和虚
39+
拟机栈合二为一。与虚拟机栈类似,本地方法栈也会抛出StackOverflowError和OutOfMemoryError。
40+
* 方法区
41+
方法区是一个比较重要的区域,java虚拟机规范中把方法区描述为堆的一个逻辑部分,但是为了和Heap(堆区)对应,也称Non-Heap(非堆区)。
42+
主要存储的是静态变量,常量(包括运行时常量),类的加载信息和java编译后的代码。这部分空间不需要连续,可以选择固定大小和可扩展,通常在这部分是没
43+
有GC的,因为GC回收的都是些静态变量,常量和类的加载信息,这些对象回收效果通常不尽人意,因此可以选择不实现垃圾回收。这块区域也称为持久代,
44+
当这块内存不足时,也会报OutOfMemoryError异常。
45+
* 堆区
46+
Java堆区是JVM内存中最胖的一块区域,因为这里存储的都是对象的实例和数组对象。这块区域是线程共享的,在JVM启动时就会创建,想想如果这么大的空间是线程私有的,那内存不得爆掉吗?
47+
按照java虚拟机规范,堆区的内容可以物理上不连续,只要逻辑上连续即可,在实现时可以是固定大小的,也可以是可扩展的,而且通常都是可扩展的,我们常用的内存参数-Xms和-Xmx就是用来调节堆大小的。
48+
java堆区按生命周期不同,分为新生代和老年代。新生代又可以细分为Eden和Survivor区,而Survivor又可以细分为Survivor1和Survivor2,这两者通常只使用其中一块,
49+
另一块用来GC时保留存活的对象。大部分的new出来的对象都是存放在Eden区,如果是大对象,比如一个很大的数组或者List对象,可以通过JVM参数-XX:PretenureSizeThreshold将超过指定大小的对象直接存入到老年代,需要注意的是,写程序时应该尽量避免朝生夕死的大对象进入老年代,因为相比年轻代的GC,老年代GC的成本更大。Eden和Survivor的默认大小比值的8:1:1,新生代默认的GC算法是复制算法。老年代的默认GC算法是标记整理法。关于这2种GC算法,会在下篇博客讲解。
50+
当堆中没有足够内存时,会抛出OutOfMemoryError异常。关于堆区的内存模型,可以参考下面的图片:
1751
* @author dell
1852
*/
1953
public class JVMInfoTest {

0 commit comments

Comments
 (0)