目录
集合框架关系与区别
ArrayList与HashSet区别
是否有顺序
能否重复
ArrayList和LinkedList区别
插入数据
定位数据
HashMap和Hashtable的区别
HashSet LinkedHashSet TreeSet
ArrayList与HashSet区别
是否有顺序
- ArrayList: 有顺序
- HashSet: 无顺序
- HashSet的具体顺序,既不是按照插入顺序,也不是按照hashcode的顺序。
- 不保证Set的迭代顺序; 确切的说,在不同条件下,元素的顺序都有可能不一样
- 换句话说,同样是插入0-9到HashSet中, 在JVM的不同版本中,看到的顺序都是不一样的。 所以在开发的时候,不能依赖于某种臆测的顺序,这个顺序本身是不稳定的
package collection; import java.util.ArrayList; import java.util.HashSet; public class TestCollection { public static void main(String[] args) { ArrayList
numberList =new ArrayList (); //List中的数据按照插入顺序存放 System.out.println("----------List----------"); System.out.println("向List 中插入 9 5 1"); numberList.add(9); numberList.add(5); numberList.add(1); System.out.println("List 按照顺序存放数据:"); System.out.println(numberList); System.out.println("----------Set----------"); HashSet numberSet =new HashSet (); System.out.println("向Set 中插入9 5 1"); //Set中的数据不是按照插入顺序存放 numberSet.add(9); numberSet.add(5); numberSet.add(1); System.out.println("Set 不是按照顺序存放数据:"); System.out.println(numberSet); } } 能否重复
- List中的数据可以重复
- Set中的数据不能够重复
- 重复判断标准是:
- 首先看hashcode是否相同
- 如果hashcode不同,则认为是不同数据
- 如果hashcode相同,再比较equals,如果equals相同,则是相同数据,否则是不同数据
- 案例演示:
- 生成50个 0-9999之间的随机数,要求不能有重复的
- 使用Set来存放随机数,不断的向里塞,直到塞满50个位置。 因为Set有不重复的特性,所以最后得到的50个,就一定是不重复的
package collection; import java.util.HashSet; import java.util.Set; public class TestCollection { public static void main(String[] args) { Set
numbers =new HashSet<>(); while(numbers.size()<50){ int i = (int) (Math.random()*10000); numbers.add(i); } System.out.println("得到50个不重复随机数:"); System.out.println(numbers); } } ArrayList和LinkedList区别
- ArrayList 插入,删除数据慢
- LinkedList, 插入,删除数据快
- ArrayList是顺序结构,所以定位很快,指哪找哪。 就像电影院位置一样,有了电影票,一下就找到位置了。
- LinkedList 是链表结构,就像手里的一串佛珠,要找出第99个佛珠,必须得一个一个的数过去,所以定位慢
插入数据
package collection; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class TestCollection { public static void main(String[] args) { List
l; l = new ArrayList<>(); insertFirst(l, "ArrayList"); l = new LinkedList<>(); insertFirst(l, "LinkedList"); } private static void insertFirst(List l, String type) { int total = 1000 * 100; final int number = 5; long start = System.currentTimeMillis(); for (int i = 0; i < total; i++) { l.add(0, number); } long end = System.currentTimeMillis(); System.out.printf("在%s 最前面插入%d条数据,总共耗时 %d 毫秒 %n", type, total, end - start); } } 定位数据
package collection; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class TestCollection { public static void main(String[] args) { List
l; l = new ArrayList<>(); modify(l, "ArrayList"); l = new LinkedList<>(); modify(l, "LinkedList"); } private static void modify(List l, String type) { int total = 100 * 1000; int index = total/2; final int number = 5; //初始化 for (int i = 0; i < total; i++) { l.add(number); } long start = System.currentTimeMillis(); for (int i = 0; i < total; i++) { int n = l.get(index); n++; l.set(index, n); } long end = System.currentTimeMillis(); System.out.printf("%s总长度是%d,定位到第%d个数据,取出来,加1,再放回去%n 重复%d遍,总共耗时 %d 毫秒 %n", type,total, index,total, end - start); System.out.println(); } }
- 案例演示:
- 比较 ArrayList和LinkedList 在最后面插入100000条数据,谁快谁慢?为什么
- 直接调用add方法,就表示在最后插入数据
- 因为是插入在最后面,所以对于数组而言,并没有一个移动很多数据的需要,所以也非常的快
- 而链表本身就很快,无论插入在哪里
package collection; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class TestCollection { public static void main(String[] args) { List
l; l = new ArrayList<>(); insertFirst(l, "ArrayList"); l = new LinkedList<>(); insertFirst(l, "LinkedList"); } private static void insertFirst(List l, String type) { int total = 1000 * 100; final int number = 5; long start = System.currentTimeMillis(); for (int i = 0; i < total; i++) { //直接add就表示插入在最后 l.add(number); } long end = System.currentTimeMillis(); System.out.printf("在%s 最后面插入%d条数据,总共耗时 %d 毫秒 %n", type, total, end - start); } }
- 在List的中间位置,插入数据,比较ArrayList快,还是LinkedList快,并解释为什么?
l.add(l.size()/2,number);
- 表示在当前容器的一半的位置,插入数据
- 在这个位置插入数据
- 数组定位很快,插入数据比较慢
- 链表定位很慢,插入数据比较快
- 最后发现,当总数是10000条的时候,链表定位的总开支要比数组插入的总开支更多,所以最后整体表现,数组会更好。
- 如果总数是1000条,结果可能就不一样了。
package collection; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class TestCollection { public static void main(String[] args) { List
l; l = new ArrayList<>(); insertFirst(l, "ArrayList"); l = new LinkedList<>(); insertFirst(l, "LinkedList"); } private static void insertFirst(List l, String type) { int total = 1000 * 100; final int number = 5; long start = System.currentTimeMillis(); for (int i = 0; i < total; i++) { //把当前容器的一半的位置,插入数据 l.add(l.size()/2,number); } long end = System.currentTimeMillis(); System.out.printf("在%s 最中间插入%d条数据,总共耗时 %d 毫秒 %n", type, total, end - start); } }
HashMap和Hashtable的区别
- HashMap和Hashtable都实现了Map接口,都是键值对保存数据的方式
- 区别1:
- HashMap可以存放 null
- Hashtable不能存放null
- 区别2:
- HashMap不是线程安全的类
- Hashtable是线程安全的类
package collection; import java.util.HashMap; import java.util.Hashtable; public class TestCollection { public static void main(String[] args) { //HashMap和Hashtable都实现了Map接口,都是键值对保存数据的方式 HashMap
hashMap = new HashMap (); //HashMap可以用null作key,作value hashMap.put(null, "123"); hashMap.put("123", null); Hashtable hashtable = new Hashtable (); //Hashtable不能用null作key,不能用null作value hashtable.put(null, "123"); hashtable.put("123", null); } }
- 案例演示:
使用如下键值对,初始化一个HashMap: adc - 物理英雄 apc - 魔法英雄 t - 坦克 对这个HashMap进行反转,key变成value,value变成key 提示: keySet()可以获取所有的key, values()可以获取所有的value
package collection; import java.util.Collection; import java.util.HashMap; import java.util.Set; public class TestCollection { public static void main(String[] args) { HashMap
map = new HashMap<>(); HashMap temp = new HashMap<>(); map.put("adc", "物理英雄"); map.put("apc", "魔法英雄"); map.put("t", "坦克"); System.out.println("初始化后的Map:"); System.out.println(map); Set keys = map.keySet(); for (String key : keys) { String value = map.get(key); temp.put(value, key); } map.clear(); map.putAll(temp); System.out.println("反转后的Map:"); System.out.println(map); } }
HashSet LinkedHashSet TreeSet
- HashSet: 无序
- LinkedHashSet: 按照插入顺序
- TreeSet: 从小到大排序
package collection; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.TreeSet; public class TestCollection { public static void main(String[] args) { HashSet
numberSet1 =new HashSet (); //HashSet中的数据不是按照插入顺序存放 numberSet1.add(88); numberSet1.add(8); numberSet1.add(888); System.out.println(numberSet1); LinkedHashSet numberSet2 =new LinkedHashSet (); //LinkedHashSet中的数据是按照插入顺序存放 numberSet2.add(88); numberSet2.add(8); numberSet2.add(888); System.out.println(numberSet2); TreeSet numberSet3 =new TreeSet (); //TreeSet 中的数据是进行了排序的 numberSet3.add(88); numberSet3.add(8); numberSet3.add(888); System.out.println(numberSet3); } }
- 既不重复,又有顺序
- 利用LinkedHashSet的既不重复,又有顺序的特性,把Math.PI中的数字,按照出现顺序打印出来,相同数字,只出现一次
package collection; import java.util.LinkedHashSet; import java.util.Set; public class TestCollection { public static void main(String[] args) { Set
result = new LinkedHashSet<>(); String str = String.valueOf(Math.PI); // 去掉点 str = str.replace(".", ""); char[] cs = str.toCharArray(); for (char c : cs) { int num = Integer.parseInt(String.valueOf(c)); result.add(num); } System.out.printf("%s中的无重复数字是:%n",String.valueOf(Math.PI)); System.out.println(result); } }