java 中的集合
set(集)、list(列表)和 map(映射)。
区别嘛 HASHMAP 只有 KEY 和 value 值对应的。。set 是可以自动清楚相同的元素
list 是其对象以线性方式存储,没有特定顺序,只有一个开头和一个结尾,当然,它与根
本没有顺序的集是不同的。
列表在数据结构中分别表现为:数组和向量、链表、堆栈、队列。
List、Map、Set 三个接口存取元素时,各有什么特点?
List 以特定索引来存取元素,可以有重复元素。Set 不能存放重复元素(用对象的
equals()方法来区分元素是否重复)。Map 保存键值对(key-value pair)映射,映射关系
可以是一对一或多对一。Set 和 Map 容器都有基于哈希存储和排序树的两种实现版本,基
于哈希存储的版本理论存取时间复杂度为 O(1),而基于排序树版本的实现在插入或删除元
素时会按照元素或元素的键(key)构成排序树从而达到排序和去重的效果。
List接口
有序的 collection(也称为序列)
特点
1、 数据有序
2、 允许存放重复元素
3、 元素都有索引
常用方法
ListIterator listIterator()
返回此列表元素的列表迭代器(按适当顺序)。
ListIterator listIterator(int index)
返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
void add(int index, E element)
在列表的指定位置插入指定元素(可选操作)。
boolean addAll(int index, Collection<? extends E> c)
将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
List subList(int fromIndex, int toIndex)
返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
E get(int index)
返回列表中指定位置的元素。
int indexOf(Object o)
返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1。
public static void main(String[] args) {
//1、创建List对象
//特点1:List集合元素都有索引,可以根据索引直接定位元素
List list = new ArrayList();
//2、常用方法
list.add(111);
list.add(222);
list.add(333);
list.add(444);
list.add('a');
list.add("abc");
list.add(3,666);//在3的索引处添加指定元素
//特点2:元素有序, 怎么存就怎么放
System.out.println(list);//[111, 222, 333, 666, 444, a, abc]
Object obj = list.get(4);//从0开始,get(m)-m是索引值,获取指定索引位置的元素
System.out.println(obj);
//3、迭代/遍历集合中的元素
//使用Collection接口提供的iterator()
Iterator it = list.iterator();
while(it.hasNext()) {//判断集合里有没有下个元素
Object o = it.next();
// System.out.println(o);
}
//使用List接口提供的listIterator()
//interfaceListIterator extends Iterator
//区别:可以使用父接口的功能,同时拥有自己的特有功能,不仅顺序向后迭代还可以逆向迭代
ListIterator it2 = list.listIterator();
while(it2.hasNext()) {
Object o = it2.next();
// System.out.println(o);
}
System.out.println();
List list2 = list.subList(1, 3);//subList(m,n)-m是开始索引,n是结束索引,其中含头不含尾类似于String.subString(m,n)
System.out.println(list2);
}
ArrayList
new ArrayList():初始容量是10
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add("aaa");//存入数据
list.add("123");
list.add("ccc");
list.add("ddd");
System.out.println(list);//list中内容
System.out.println(list.size());//集合长度
System.out.println(list.get(1));//根据下标获取元素
System.out.println();
System.out.println(list.remove(2));//移除下标对应的元素
System.out.println(list);
//下标遍历
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i));
}
//Iterator迭代遍历,封装了下标
Iterator<String> it = list.iterator();
while (it.hasNext()) {//如果有数据
String s = it.next();//一个一个向后遍历
System.out.println(s);
}
}
ArrayList扩容
ArrayList的容量变为10 (如下图一);之后扩容会按照1.5倍增长。也就是当添加第11个数据的时候,Arraylist继续扩容变为10*1.5=15(如下图二);当添加第16个数据时,继续扩容变为15 * 1.5 =22个
LinkedList
双向链表,两端效率高。底层就是数组和链表实现的。
常用方法
add()
get()
size()
remove(i)
remove(数据)
iterator()
addFirst() addLast()
getFirst() getLast()
removeFirst() removeLast()
双向链表:下标遍历效率低,迭代器遍历效率高
Set接口
一个不包含重复元素的 collection。
数据无序(因为set集合没有下标)。
由于集合中的元素不可以重复。常用于给数据去重
HashSet:底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部的HashMap中。当然K仍然不许重复。
Ø TreeSet:底层就是TreeMap,也是红黑树的形式,便于查找数据。
Ø HashMap实现中,当哈希值相同的对象,会在同一个hash值的位置存储不同属性的数据。
常用方法
boolean add(E e):添加元素。
boolean addAll(Collection c):把小集合添加到大集合中 。
boolean contains(Object o) : 如果此 collection 包含指定的元素,则返回 true。
boolean isEmpty() :如果此 collection 没有元素,则返回 true。
Iterator iterator():返回在此 collection 的元素上进行迭代的迭代器。
boolean remove(Object o) :从此 collection 中移除指定元素的单个实例。
int size() :返回此 collection 中的元素数。
Objec[] toArray():返回对象数组
HashSet
哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
添加对象时要重写hashCode()与equals(),不然不能去重
Map接口
Ø 可以根据键 提取对应的值
Ø 键不允许重复,如果重复值会被覆盖
Ø 存放的都是无序数据
Ø 初始容量是16,默认的加载因子是0.75
常用方法
void clear()
从此映射中移除所有映射关系(可选操作)。
boolean containsKey(Object key)
如果此映射包含指定键的映射关系,则返回 true。
boolean containsValue(Object value)
如果此映射将一个或多个键映射到指定值,则返回 true。
V get(Object key)
返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
boolean isEmpty()
如果此映射未包含键-值映射关系,则返回 true。
V put(K key, V value)
将指定的值与此映射中的指定键关联(可选操作)。
void putAll(Map<? extends K,? extends V> m)
从指定映射中将所有映射关系复制到此映射中(可选操作)。
V remove(Object key)
如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
int size()
返回此映射中的键-值映射关系数。
Set<Map.Entry<K,V>> entrySet()
返回此映射所包含的映射关系的 Set 视图。
map.put(null,null);//可以存入键为null,值也null的数据
//map集合的遍历,
//方式1:keySet():把map中的可以放入set集合
//遍历方式1:keySet ()
Set set = m.keySet();
Iterator it = set.iterator();
while(it.hasNext()) {
String key = (String) it.next();
String val = (String) m.get(key);
System.out.println(key+"="+val);
}
//遍历方式2:entrySet ()
Set set2 = m.entrySet();
Iterator it2 = set2.iterator();
while(it2.hasNext()) {
Entry en = (Entry) it2.next();
String key = (String) en.getKey();
String value = (String) en.getValue();
System.out.println(key+"=="+value);
}
HashMap
HashMap的键要同时重写hashCode()和equals()
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。
HashMap底层是一个Entry数组,当存放数据时会根据hash算法计算数据的存放位置。算法:hash(key)%n,n就是数组的长度。
当计算的位置没有数据时,就直接存放,当计算的位置有数据时也就是发生hash冲突的时候/hash碰撞时,采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。
ArrayList 和 LinkedList 的区别
1.ArrayList 是实现了基于动态数组的数据结构,LinkedList 基于链表的数据结构。
2.对于随机访问 get 和 set,ArrayList 觉得优于 LinkedList,因为 LinkedList 要移动指
针。
3.对于新增和删除操作 add 和 remove,LinedList 比较占优势,因为 ArrayList 要移动数
据。
Collection 是对象集合, Collection 有两个子接口 List 和 Set,
List 可以通过下标 (1,2…) 来取得值,值可以重复,而 Set 只能通过游标来取值,并且值是不能重复的
ArrayList , Vector , LinkedList 是 List 的实现类
ArrayList 是线程不安全的, Vector 是线程安全的,这两个类底层都是由数组实现的
LinkedList 是线程不安全的,底层是由链表实现的
Map 是键值对集合
HashTable 和 HashMap 是 Map 的实现类
HashTable 是线程安全的,不能存储 null 值
HashMap 不是线程安全的,可以存储 null 值
ArrayList、Vector、LinkedList 的存储性能和特性
ArrayList 和 Vector 都是使用数组方式存储数据,此数组元素数大于实际存储的数据以
便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等
内存操作,所以索引数据快而插入数据慢,Vector 中的方法由于添加了 synchronized 修饰,
因此 Vector 是线程安全的容器,但性能上较 ArrayList 差,因此已经是 Java 中的遗留容器。
LinkedList 使用双向链表实现存储(将内存中零散的内存单元通过附加的引用关联起来,形
成一个可以按序号索引的线性结构,这种链式存储方式与数组的连续存储方式相比,内存的
利用率更高),按序号索引数据需要进行前向或后向遍历,但是插入数据时只需要记录本项
的前后项即可,所以插入速度较快。Vector 属于遗留容器(Java 早期的版本中提供的容器,
除此之外,Hashtable、Dictionary、BitSet、Stack、Properties 都是遗留容器),已经不推荐使
用,但是由于 ArrayList 和 LinkedListed 都是非线程安全的,如果遇到多个线程操作同一个容
器的场景,则可以通过工具类 Collections 中的 synchronizedList 方法将其转换成线程安全的
容器后再使用(这是对装潢模式的应用,将已有对象传入另一个类的构造器中创建新的对象
来增强实现)。
HashMap 和 HashTable 的区别
在 Java 2 以前,一般使用 Hashtable 来映射键值和元素。为了使用 Java 集合框架,Java
对 Hashtable 进行了重新设计,但是,为了向后兼容保留了所有的方法。Hashtable 实现
了 Map 接口,除了 Hashtable 具有同步功能之外,它与 HashMap 的用法是一样的。·
在使用时一般是用 ArrayList 代替 Vector,LinkedList 代替 Stack,HashMap 代替
HashTable,即使在多线程中需要同步,也是用同步包装类。
集合类中 List、Map、Set 的区别
List 和 Set 继承了 Collection 接口,而 map 不是;
List 中存放元素有顺序并且可以重复;
set 中存放的元素是无序并且是不可能重复的;
Map 中存放是键值对。
Collection 和 Collections 的区别
Collection 是 java.util 下的接口,它是各种集合的父接口,
继承于它的接口主要有 Set 和 List;Collections 是个 java.util 下的类,
是针对集合的帮助类,提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操
作。
常用方法
Collections.sort(List<> list):根据元素的自然顺序 对指定列表按升序进行排序。
Collections.max():根据元素的自然顺序,返回给定 collection 的最大元素。
Collections.min():根据元素的自然顺序 返回给定 collection 的最小元素。
Collections.swap(List,i,j):在指定列表的指定位置处交换元素。
Collections.addAll():
public static void main(String[] args) {
List<String> list = new ArrayList();
//添加多个元素
Collections.addAll(list,
"3","30","23","15","29","12","26");
//元素排序
Collections.sort(list);
//默认是字符顺序:[12,15,23,26,29, 3, 30]
System.out.println(list);
//自己定义比较方式
Collections.sort(list, new Comparator<String>() {
//自定义比较器,sort()自动调用
@Override
public int compare(String o1, String o2) {
//把字符串转成int比大小
int a = Integer.parseInt(o1);
int b = Integer.parseInt(o2);
//o1大是正数,o1小是负数,相等是0
return a-b;
}
});
System.out.println(list);
}
HashSet: 哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用 null 元素。
添加对象时要重写hashCode()与equals(),不然不能去重
HashSet :内部封装了 HashMap 和 TreeMap,数据保存在键这一列
LinkedHashMap(哈希表,存放数据以链表来连接,数组存放无序但链表连接有序,
可看做一个有序的 HashMap),既可快速定位,查找数据,又可以使数据存放有序
ConcurrentHashMap(分段加锁)Concurrent-同步
泛型
l E - Element (在集合中使用,因为集合中存放的是元素)
l T - Type(Java 类)
l K - Key(键)
l V - Value(值)
l N - Number(数值类型)
l ? - 表示不确定的java类型
Iterator it = list.iterator();
while(it.hasNext()) {
Integer s = (Integer) it.next();
System.out.println(s);
}
Collection接口
英文名称Collection,是用来存放对象的数据结构。其中长度可变,而且集合中可以存放不同类型的对象。并提供了一组操作成批对象的方法。
数组的缺点:长度是固定不可变的,访问方式单一,插入、删除等操作繁琐。
常用方法
boolean add(E e):添加元素。
boolean addAll(Collection c):把小集合添加到大集合中 。
boolean contains(Object o) : 如果此 collection 包含指定的元素,则返回 true。
boolean isEmpty() :如果此 collection 没有元素,则返回 true。
Iterator iterator():返回在此 collection 的元素上进行迭代的迭代器。
boolean remove(Object o) :从此 collection 中移除指定元素的单个实例。
int size() :返回此 collection 中的元素数。
Objec[] toArray():返回对象数组
//for遍历集合
for(int i =0 ;i<c.size();i++) {
System.out.println(c.toArray()[i]);
}
//iterator迭代器遍历
Iterator it = c.iterator();//对 collection 进行迭代的迭代器
while (it.hasNext()) {//如果仍有元素,则返回 true
System.out.println(it.next());//返回迭代获取到的下一个元素
}