集合
集合
1.什么是集合?有什么用?
- 集合实际上就是一个容器。可以来容纳其它类型的数据。
2.集合存储的数据
- 集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,集合当中存储的都是java对象的内存地址。(或者说集合中存储的是引用。) 集合在java中本身是一个容器,是一个对象。集合中任何时候存储的都是"引用"。
- 存储基本数据类型实际上是对基本数据类型进行包装
Collection c=new ArrayList();
c.add(1);//自动装箱Interger
3.在java中每一个不同的集合,底层会对应不同的数据结构。
往不同的集合中存储元索,等于将数据放到了不同的数据结构当中。(数据存储的结构就是数据结构)不同的数据结构,数据存储方式不同。
例如:
数组、二叉树、链表、哈希表… .
集合继承结构图
Collection
Map
Collection 接口
Collection接口中的方法:
1.add(object)向集合中添加元素(boolean)
Collection c=new ArrayList();
c.add("asd");
2.size()获取集合中元素的个数(int)
Collection c=new ArrayList();
c.add("asd");
c.add(100);
System.oyut.println(c.size());
结果:2
3.clear清空集合(void)
Collection c=new ArrayList();
c.add("asd");
c.clear();
System.oyut.println(c.size());
结果:0
4.contains(Object o)判断当前集合中是否包含元素o,包含返回true ,不包含返回(boolean)
(contsains方法实现原理)
Collection c=new ArrayList();
c.add("asd");
c.contains("asd");
5.remove(object o)删除集合中的某个元素。(boolean)
Collection c=new ArrayList();
c.remove("asd");
6.isEmpty()郸断该集合中元素的个数是否为0(boolean)
Collection c=new ArrayList();
c.isEmpty();
7.toArray()调用这个方法可以把集合转换成数组。(0bject[ ] )
Collection c=new ArrayList();
Object[] oj=c.toArray();
List接口
List集合存储元秦特点:
有序可重复
- 有序:List集合中的元素有下标。从0开始,以1递增。
- 可重复:存储一个1,还可以再存储1.
List接口常用方法:
1.add(int index,0bject element)添加元素 (void)
List l=new ArrayList();
l.add(1,"a");
l.add(2,"b");
2.get(int index)获取当前下标元素(Object)
List l=new ArrayList();
l.add(0,"a");
l.add(1,"b");
l.get(0);
结果:a
- indexOf(object o)获取元素第一次出现的下标(int)
List l=new ArrayList();
l.add(0,"a");
l.add(1,"a");
l.indexOf("a");
结果:0
- lastIndex0f(object o)获取元素最后一次出现的下标(int)
List l=new ArrayList();
l.add(0,"a");
l.add(1,"a");
l.latIndexOf("a");
结果:1
5.remove(int index)删除当前下标元素(Object)
List l=new ArrayList();
l.add(0,"a");
l.remove(0);
- set(int index, object element)修改指定下标元素(Object)
List l=new ArrayList();
l.add(0,"a");
l.set(0,"b");
集合的遍历
ArrayList集合
ArrayList集合底层采用了数组数据结构
ArrayList集合是非线程安全的。
- 1、ArrayList集合初始化容里是10
- 2、ArrayList集合底层是Object类型的数组Object[]
- 3、扩容到原容里的1.5倍。
int newCapacity = ArraysSupport .newLength(oldCapacity ,
minCapacity - oldCapacity,
oldcapacity >>1)
右移一位=原始值的一半(即扩大了1.5倍)=增加的量
新容量=原容量+增加的量=10+5=10*1.5=15
- 4、建议给定一个预估计的初始化容里,减少数组的扩容次数,这是ArrayList集合比较重要的优化策略。
- 5、数组的优点:检索效率比较高
- 6:、教组的缺点:随机增删元素效率比较低。
LinkedList集合
LinkedList集合底层采用了双向链表数据结构
节点是双向链表中基本的单元。每一个节点Node都有三个属性;
- 存储的数据。
- 下一个节点的内存地址。
- 上一个节点的内存地址。
链表的优点:
由于链表上的元素在空间存储上内存地址不连续。所以随机增删元素的时候不会有大量元素位移,因此随机增删效率较高。
链表的缺点:
不能通过数学表达式计算被查找元素的内存地址,每一次查找都是从头节点开始遍历,直到找到为止。所以LinkedList集合检索/查找的效率较低。
注意:ArrayList之所以检索效率比较高,不是单纯因为下标的原因。是因为底层数组发挥的作用。linkedList集合照样有下标,但是检索,查找某个元素的时候只能从头节点开始,因此效率比较低。
Vector集合
Vector集合底层采用了数组数据结构
1、初始化容量: 10
2、怎么扩容的?
扩容之后是原容量的2倍。10–>20
3.Vector中所有的方法都是线程同步的,都带有synchronized关键字,是线程安全的。效率比较低。
5.线程不安全集合转换成线程安全集合
使用集合工具类:java.util.collections;
List l=new ArrayList();
Collections.synchronized(l);
Set集合
HashSet集合
实际上HashSet集合在new的时候,底层实际上new了—个HashMap集合。
向HashSet集合中存储元素,实际上是存储到HashMap集合(哈希表数据结构)中了。
- Hashset集合初始化容里16
- 初始化容里建议是2的倍数。
- 扩容:扩容之后是原容量的2倍。
SortedSet接口
SortedSet集合存储元素的特点:由于继承了Set集合,所以它的特点也是无序不可重复,但是放在SortedSet集合中的元素可以按照大小顺序自动排序.
TreeSet集合
- 1、TreeSet集合底层实际上是一个TreeMap、 TreeMap集合底层是一个二叉树。
- 2、放到TreeSet集合中的元素,等同于放到TreeMap集合key部分了。
- 3、TreeSet集合中的元素:无序不可重复,但是可以按照元素的大小顺序自动排序。称为:可排序集合。
Set<Integer> s=new TreeSet();
s.add(1);
s.add(5);
s.add(2);
s.add(10);
for(Integer i:s){
System.out.println(i);
}
结果:
1
2
5
10
自定义类型的排序
TreeSet集合自定义类型的排序
Map接口
- 1、Map和collection没有继承关系。
- 2、Nap集合以key和value的方式存储数据:键值对
key和value都是引用数据类型。
key和value都是存储对象的内存地址。
key起到主导的地位,value是key的一个附属品。
Map集合的遍历
Map接口中接口的方法:
- put( key, value)向Nap集合中添加键值对
Map m=new HashMap();
m.put(1,"a");
- get(object key)通过key获取value
Map m=new HashMap();
m.put(1,"a");
m.get(1);
- clear()清空Map集合(void )
Map m=new HashMap();
m.clear();
- containsKey(object key)判断Map中是否包含某个key(boolean )
Map m=new HashMap();
m.put(1,"a");
m.containsKey(1);
结果:true
- containsvalue(object value)判断Map中是否包含某个value(boolean )
Map m=new HashMap();
m.put(1,"a");
m.containsValue("a");
结果:true
- isEmpty()判断Map集合中元素个数是否为e(boolean )
Map m=new HashMap();
m.isEmpty();
- keySet()获取Map集合所有的key (所有的键是一个set集合)(Set )
Map m=new HashMap();
m.put(1,"a");
m.put(2,"a");
Set s=m.keySet();
System.out.println(s);
结果:[1,2]
- remove( object key)通过key删除键值对
Map m=new HashMap();
m.put(1,"a");
m.remove(1);
9.size()获取Map集合中键值对的个数。(int )
Map m=new HashMap();
m.size();
- values()获取Map集合中所有的value ,返回一个collection(collection)
Map m=new HashMap();
m.put(1,"a");
m.put(2,"b");
Collection<String> c=m.values();;
System.out.println(c);
结果:["a","b"]
11.entrySet()|将Map集合转换威set集合(Set<Map.Entry<K,V>> )
Map m=new HashMap();
m.put(1,"a");
m.put(2,"b");
Set<Map.Entry<Intrger,String>> s=m.entrySet();
System.out.println(s);
结果:
[1=a,2=b]
Map.Entry是Map中的静态内部类
HashMap
HashMap集合底层是哈希表/散列表的数据结构。
如果哈希表单向链表中元素超过8个,单向链表会变成红黑树数据结构。当红黑树上的节点数里小于6时,会重新把红黑树变成单向链表数据结构。
1、哈希表是一个怎样的数据结构呢?
- 哈希表是一个一维数组和单向链表的结合体。这个数组中每一个元素是一个单向链表。
1.数组:在查询方面效率很高,随机增删方面效率很低。
2.单向链表:在随机增删方面效率较高,在查询方面效率很低。
3.哈希表将以上的两种数据结构融合在一起,充分发挥它们各自的优点。
为什么哈希表的随机增删,以及查询效率都很高?
- 增删是在链表上完成。
- 查询也不需要都扫描,只需要部分扫描。
2.HashMNap结构图
3、HashMNap集合底层的源代码;
public class HashMap{
Node<K,V>[ ] tabLe;
//静态的内部类HashMap.Node
static class Node<K,V>{
final int hash;//哈希值(哈希值是key的hashCode()方法的
//执行结果。hash值通过哈希函数/算法,可以计算出key值所对应的下标
final K key; //存储到Map集合中的那个key
v value;//存储到Map集合中的那个vaLue
Node<K ,V> next;//下一个节点的内存地址。
}
}
4.HashMap集合的key部分特点:
- 无序
因为不一定挂到单向链表上哪个位置。 - 不可重复。
equals方法来保证HashMap集合的key不可重复。如果key重复了,value会覆盖。
HashMap集合的key部分允许null,但只能有一个null值
5.HashMNap实现put和get方法的底层原理
put()方法
- 先将看k,v封装到node对象中去,通过HashCode()方法得出hash值,再通过哈希算法将得出hash值转换成数组的下标,下标位置上如果没有任何元素,就把node对象直接添加,如果对应的下标上有链表,此时会拿着要添加node对象中的key和链表中的key一 一比较(equals),如何所有的equals方法的结果都是false,那么将这个节点放到链表的最后。如何有一个返回true,则覆盖key所对应的value
get()方法
- 先调用k的hashCode0方法得出哈希值,通过哈希算法转换成数组下标,通过数组下标快速定位到某个位置上,如果这个位置上什么也没有,返回null。如果这个位置上有单向链表,那么会拿着参数k和单向链表上的每个节点中的k进行equals,如果所有equals方法返回false,那么get方法返回null,只要其中有一个节点的k和参数kequals的时候返回true,那么此时这个节点的value就是我们要找的value , get方法最终返回这个要找的value.
8、HashMap集合的默认初始化容量
HashMap集合的默认初始化容量是16,默认加载因子是0.75
这个默认加载因子是当HashMap集合底层数组的容量达到75%的时候,数组开始扩容。
重点,记住:HashMap集合初始化容量必须是2的倍数,这是因为达到散列均匀,为了提高HashMap集合的存取效率,所必须的。
HashTable集合
Hashtable集合底层是哈希表数据结构,
- 1.是线程安全的·其中所有的方法都带有synchronized关键字:效率较低,现在使用较少了,因为空制线程安全有其它更好的方案。
- 2.Hashtable的约key和value不允许null
- 3.Hashtable集合初始化容量11
- 4.Hashtable集合扩容是:原容里*2+1
Properties集合
- Properties是一个Map集合,继承Hashtable集合。
- Properties的key和value都是String类型。
- Properties被称为属性类对象。
- Properties是线程安全的。
Properties的存取方法
1.setProperty(“key”,“vaule”);
Properties p=new Properties();
p.serProperties("name","zhangsan");
2.getProperty(“key”);(通过key获取value)
p.getProperty("name");
SortedMap接口
SortedMap集合的key存储元素的特点:
无序不可重复的,另外放在SortedMap集合key部分的元素会自动按照大小顺序排序,称为可排序的集合.