255目录
目录
3,(map不实现collection接口)为什么引入ConcurrentHashMap
1,HashTable几乎可以等价HashMap
HashTable是JDK1.0的java特性,它是线程安全的,而HashMap非线程安全的,HashTable支持序列化,因此在单线程的环境下HashTable相比HashMap效率要第。HashTable不支持key和value为空,而HashMap没有这个限制。
2,HashSet和HashList
HashSet实现了Set接口,它不允许集合中有重复的值,当我们提到HashSet时,第一件事情就是在将对象存储在HashSet之前,要先确保对象重写equals()和hashCode()方法
如果不重写上述两个方法,那么将使用下面方法默认实现:
public boolean add(Object obj)方法用在Set添加元素时,如果元素值重复时返回 "false",如果添加成功则返回"true"
这样才能比较对象的值是否相等,以确保set中没有储存相等的对象。如果我们没有重写这两个方法,将会使用这个方法的默认实现
重写equals()的原因
Object的equal方法默认是两个对象的引用的比较,意思就是指向同一内存。
但是,String对象中equals方法是判断值的,而==是地址判断(因为JDK重写了)。
我们很大部分时间都是进行两个对象的比较(而不是比较引用),这个时候Object的equals()方法就不可以了,所以才会有String这些类对equals方法的改写,依次类推Double、Integer、Math等等这些类都是重写了equals()方法的,从而进行的是内容的比较。
重写equals()后要重写hashCode()的理由
java.lnag.Object中对hashCode的约定:
- 在一个应用程序执行期间,如果一个对象的equals方法做比较所用到的信息没有被修改的话,则对该对象调用hashCode方法多次,它必须始终如一地返回同一个整数。
- 如果两个对象根据equals(Object o)方法是相等的,则调用这两个对象中任一对象的hashCode方法必须产生相同的整数结果。
- 如果两个对象根据equals(Object o)方法是不相等的,则调用这两个对象中任一个对象的hashCode方法,不要求产生不同的整数结果。但如果能不同,则可能提高散列表的性能。
只要改写了就会违约,所以要继续改写。
3,(map不实现collection接口)为什么引入ConcurrentHashMap
- HashMap和HashTable:HashMap去掉了HashTable的contains方法,但是加上了containsValue()和containsKey()方法。
- HashTable同步的,而HashMap是非同步的,效率上比HashTable要高。
- HashMap允许空键值,而HashTable不允许。
- HashMap:适用于Map中插入、删除和定位元素。 Treemap:适用于按自然顺序或自定义顺序遍历键(key)
HashMap线程不安全,它的线程不安全主要发生在put等对HashEntry有直接写操作的地方:
-
从put操作的源码不难看出,线程不安全主要可能发生在这两个地方:
-
key已经存在,需要修改HashEntry对应的value;
-
key不存在,在HashEntry中做插入。
Hashtable线程安全,但是效率低下
4,Collection常见方法
- 添加功能 boolean add(E e) 添加一个元素 boolean addAll(Collection c)
添加一批元素 - 删除功能 boolean remove(Object o) 删除一个元素
- 判断功能 boolean contains(Object o) 判断集合是否包含指定的元素 boolean isEmpty()
判断集合是否为空(集合中没有元素) - 获取功能 int size()
获取集合的长度 - 转换功能 Object[] toArray() 把集合转换为数组
- 使用技巧:
5,遍历Collection集合的方式
1.普通的for循环【必须要有索引,可以修改元素】
- 注意set集合是无序的不能使用普通for循环遍历,只能使用增强for或者迭代器遍历
import java.util.*;
public class test{
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("Hello");
list.add("Java");
list.add("World");
for (int i = 0; i < list.size(); i++){
String s = (String) list.get(i);
System.out.println(s);
}
}
}
2.迭代器遍历【任何集合都可以遍历,只能获取元素】
- 只要是Collection集合都适合
- 它是Java集合的顶层接口(不包括map系列的集合,Map接口是map系列集合的顶层接口)
1. Object next():返回迭代器刚越过的元素的引用,返回值是Object,需要强制转换成自己需要的类型。
2. boolean hasNext():判断容器内是否还有可供访问的元素。
3. void remove():删除迭代器刚越过的元素。
- 所以除了map系列的集合,我么都能通过迭代器来对集合中的元素进行遍历。
- 注意:我们可以在源码中追溯到集合的顶层接口,比如Collection接口,可以看到它继承的是类Iterable
import java.util.*;
public class test{
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
c.add("Hello");
c.add("Java");
c.add("World");
c.add("轩成笔记");
//获取迭代器对象
Iterator<String> it = c.iterator();
//hasNext()判断是否有下一个元素,如果有就用next()获取
while(it.hasNext()){
//获取下一个元素
String s = it.next();
System.out.println(s);
}
}
}
3.高级for循环【就是迭代器的简化方式】
import java.util.*;
public class test{
public static void main(String[] args) {
Collection<String> c = new HashSet<String>();
c.add("Hello");
c.add("Java");
c.add("World");
c.add("轩成笔记");
//高级for遍历集合
for (String s : c){
System.out.println(s);
}
int[] arr = {1, 2, 3, 4, 5};
//高级for遍历数组
for (int a : arr){
System.out.println(a);
}
}
}
6,map的两种遍历方式KeySet、entrySet
1. Map集合的第一 种遍历方式:通过键找值的方式
方法: Set keySet() 返回此地图中包含的键的Set视图。 实现步骤:
- 使用keySet() ,把Map集合中的所有的key取出来,存入到一-个Set集合中
- 遍历set集合,获取到Map集合中的每一 个key
- 通过Map集合中的V get(0bject key), 获取到所有的Value值,输出
public class MapTest02 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map. put( "赵丽颖", 168);
map. put("杨颖" ,165);
map. put("林志颖" ,155);
Set<String> Set = map.keySet();//返回的是一个set集合
for (String key : Set) {
Integer value = map.get(key);
System.out.println(key+" "+value);
}
}
}
2.Map集合的第二种遍历方式: 使用Entry 对象遍历
- Entry:键值对(key-value)
- 方法:
- Map接口:
- Set<Map. Entry<K, V>> entrySet() 返回此地图中包含的映射的Set视图。
- java. util Interface Map. Entry<K, V>:
- K getKey()返回与此条目相对应的键。
- V getValue() 返回与此条目相对应的值。
- 实现步骤:
- 使用Map集合中的entrySet()方法,把集合中多个Entry对象取出来,存储到一个Set 集合中
- 遍历Set集合,获取到每一个Entry
- 调用Entry中的getKey()和IgetValue()方法获取键和值
public class MapTest03 {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<>();
map. put( "赵丽颖", 168);
map. put("杨颖" ,165);
map. put("林志颖" ,155);
Set<Map.Entry<String, Integer>> set = map.entrySet();
for (Map.Entry<String, Integer> entry : set) {
System.out.println(entry.getKey()+entry.getValue());
}
}
}