集合(Conllection)
集合(Conllection)
1.1、什么是集合
存储对象的容器,面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个 对象的操作,存储对象,集合是存储对象最常用的一种方式。 集合的出现就是为了持有对象。集合中可以存储任意类型的对象, 而且长度可变。在程序 中有可能无法预先知道需要多少个对象, 那么用数组来装对象的话, 长度不好定义, 而集 合解决了这样的问题。
1.2、集合和数组的区别
数组和集合类都是容器 数组长度是固定的,集合长度是可变的。数组中可以存储基本数据类型,集合只能存储对象 数组中存储数据类型是单一的,集合中可以存储任意类型的对象。 集合类的特点 用于存储对象,长度是可变的,可以存储不同类型的对象。
-
数组的缺点:
存储类型单一的数据容器,数组一旦声明好不可变
1.3、集合的分类
Java中的集合类可以分为两大类:一类是实现Collection接口;另一类是实现Map接口。
注意 集合和数组中存放的都是对象的引用。
1.4、什么时候该用什么样的集合
Conllection | 我们需要保存若干个对象的时候使用集合。 |
---|---|
List | 如果我们需要保留存储顺序, 并且保留重复元素, 使用 List. 如果查询较多, 那么使用 ArrayList 如果存取较多, 那么使用 LinkedList 如果需要线程安全, 那么使用 Vector |
Set | 如果我们不需要保留存储顺序, 并且需要去掉重复元素, 使用 Set. 如果我们需要将元素排序, 那么使用 TreeSet 如果我们不需要排序, 使用 HashSet, HashSet 比 TreeSet 效率高. 如果我们需要保留存储顺序, 又要过滤重复元素, 那么 使用 LinkedHashSet |
2、Conllection接口
Collection 接口有两个子接口:List 和 Set
特点:
java.util.Collection
**---| Collection 描述所有接口的共性方法(如:CRUD)**
—-| List 接口 可以有重复元素的集合,元素是有序的!
—-| Set 接口 不可以有重复元素的集合,元素是无序的!
- 创建集合对象:使用 Collection 中的 List 的具体实现类 ArrayList 或者 LinkedList OR vector
2.1、Conllection的共性方法
//添加方法:
add(Object o) //添加指定元素
addAll(Collection c) //添加指定集合
//删除方法:
remove(Object o) //删除指定元素
removeAll(Collection c) //输出两个集合的交集
retainAll(Collection c) //保留两个集合的交集
clear() //清空集合
//查询方法:
size() //集合中的有效元素个数
toArray() //将集合中的元素转换成Object类型数组
//判断方法:
isEmpty() //判断是否为空
equals(Object o) //判断是否与指定元素相同
contains(Object o) //判断是否包含指定元素
containsAll(Collection c) //判断是否包含指定集合
2.2、List
2.2.1、List特有的方法
//添加方法:
add(int index, Object o) //向指定位置添加元素
addAll(int index, Collection c) //向指定位置添加集合
//删除方法
remove(int index) //删除指定元素
//查询方法:
get(int index) //获取指定位置的元素
indexOf(Object o) //获取指定元素的位置
lastIndexOf(Object o) //获取指定元素最后一次出现的位置
//修改方法:
subList(int fromIndex, int toIndex) //截取子集合从fromIndex到toIndex,要头不要尾
set(int index, Object o) //修改指定位置的元素
2.2.2、ArrayList
ArrayList:实现原理:
数组实现, 查找快, 增删慢 数组为什么是查询快?
因为数组的内存空间地址是连续的. ArrayList 底层维护了一个 Object[] 用于存储对象,默认数组的长度是 10。可以 通过 new ArrayList(20)显式的指定用于存储对象的数组的长度。 当默认的或者指定的容量不够存储对象的时候,容量自动增长为原来的容量的 1.5 倍。 13 由于 ArrayList 是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素. 所以 慢。数组是可以直接按索引查找, 所以查找时较快 可以考虑,假设向数组的 0 角标未知添加元素,那么原来的角标位置的元素需要整体往后移, 并且数组可能还要增容,一旦增容,就需要要将老数组的内容拷贝到新数组中.所以数组的 增删的效率是很低的。
ArrayList特有的方法:
ensureCapacity(int minCapactiy) //判断当前数组中的元素个数是否大于指定的minCapacity
trimToSize() //修改数组容量为当前数组有效元素个数
2.2.3、LinkedList
LinkedList:链表实现, 增删快, 查找慢
由于 LinkedList:在内存中的地址不连续,需要让上一个元素记住下一个元素.所以每个元素中 保存的有下一个元素的位置.虽然也有角标,但是查找的时候,需要从头往下找,显然是没有数 组查找快的. 但是,链表在插入新元素的时候,只需要让前一个元素记住新元素,让新元素记住 下一个元素就可以了.所以插入很快. 由于链表实现, 增加时只要让前一个元素记住自己就可以, 删除时让前一个元素记住后一个 元素, 后一个元素记住前一个元素. 这样的增删效率较高。 但查询时需要一个一个的遍历, 所以效率较低。
LinkedList特有的方法
//查询方法:
getFirst() //获取集合中的第一个元素
getLast() //获取集合中的最后一个元素
//添加方法:
addFirst(Object o) //在集合的第一个位置添加指定元素
addLast(Object o) //在集合的最后一个位置添加指定元素
//删除方法:
removeFirst() //删除集合中的第一个元素
removeLast() //删除集合中的最后一个元素
2.2.4、Vector
Vector: 描述的是一个线程安全的 ArrayList。
ArrayList: 单线程效率高
Vector : 多线程安全的,所以效率低
Vector特有的方法:
void addElement(E obj) 在集合末尾添加元素
E elementAt( int index) 返回指定角标的元素
Enumeration elements() 返回集合中的所有元素,封装到 Enumeration 对象中
2.3、Set
注重独一无二的性质,该体系集合可以知道某物是否已近存在于集合中,不会存储重复的 元素 用于存储无序(存入和取出的顺序不一定相同)元素,值不能重复。 对象的相等性 引用到堆上同一个对象的两个引用是相等的。如果对两个引用调用 hashCode 方法, 会得到相同的结果,如果对象所属的类没有覆盖 Object 的 hashCode 方法的话, hashCode 会返回每个对象特有的序号(java 是依据对象的内存地址计算出的此序号), 所以两个不同的对象的 hashCode 值是不可能相等的。 如果想要让两个不同的 Person 对象视为相等的,就必须覆盖 Object 继下来的 hashCode 方法和 equals 方法,因为 Object hashCode 方法返回的是该对象的内存 地址,所以必须重写 hashCode 方法,才能保证两个不同的对象具有相同的 hashCode, 同时也需要两个不同对象比较 equals 方法会返回 true 该集合中没有特有的方法,直接继承自 Collection。
2.3.1、HashSet
线程不安全,存取速度快。底层是以 哈希表实现的。
2.3.2、TreeSet
红-黑树的数据结构,默认对元素进行 自然排序(String)。如果在比较的 时候两个对象返回值为 0,那么元素 重复。
2.3.3、LinkedHashSet
2.4、Iterator(迭代器)
注意:Iterator 在迭代时,只能对元素进行获取(next())和删除(remove())的操作。
2.4.1、Collection中的迭代器Iterator方法
Iterator iterator(); //迭代器构造方法
boolean hasNext() //判断是否有下一个元素
Object next() //获取当前元素
void remove() //删除通过next()获取的元素,在next()之后使用,不可以单独使用
2.4.2、List特有的迭代器ListIterator方法
ListIterator listIterator(); //迭代器构造函数
boolean hasNext() //判断是否有下一个元素
boolean hasPrevious() //判断是否有上一个元素
Object next() //获取当前元素
Object previous() //获取上一个元素
void remove() //删除通过next()获取的元素,在next()之后使用,不可以单独使用
add(Object o) //添加指定元素
set(Object o) //修改指定元素
int nextIndex() //获取当前元素所在位置
2.5、Map
Map 一次存一对元素, Collection 一次存一个。Map 的键不能重复,保证唯一。 Map 一次存入一对元素,是以键值对的形式存在.键与值存在映射关系.一定要保证键的唯 一性.
—| Map 接口 将键映射到值的对象。一个映射不能包含重复的键;每个键最多只 能映射到一个值。
—| HashMap 采用哈希表实现,所以无序
**--| TreeMap 可以对健进行排序**
—|Hashtable: 底层是哈希表数据结构,线程是同步的,不可以存入 null 键,null 值。 效率较低。
—|HashMap: 底层是哈希表数据结构,线程是不同步的,可以存入 null 键,null 值。 要保证键的唯一性,需要覆盖 hashCode 方法,和 equals 方法。
—| LinkedHashMap: 该子类基于哈希表又融入了链表。可以 Map 集合进行增删提高效率。
—|TreeMap: 底层是二叉树数据结构。可以对 map 集合中的键进行排序。需要使用 Comparable 或者 Comparator 进行比较排序。return 0,来判断键的唯一 性。
2.5.1、常用方法
1、添加:
1、V put(K key, V value) (可以相同的 key 值,但是添加的 value 值会覆 盖前面的,返回值是前一个,如果没有就返回 null) 2、putAll(Map m) 从指定映射中将所有映射关 系复制到此映射中(可选操作)。
2、删除:
1、remove() 删除关联对象,指定 key 对象
2、clear() 清空集合对象
3、获取:
1:value get(key); 可以用于判断键是否存在的情况。当指定的键不存在的时候,返 回的是 null。
3、判断:
1、boolean isEmpty() 长度为 0 返回 true 否则 false
2、boolean containsKey(Object key) 判断集合中是否包含指定的 key
3、boolean containsValue(Object value) 判断集合中是否包含指定的value
4、长度:
1、Int size()
2.5.2、遍历Map的方式
- 第一种方式:使用 keySet
将 Map 转成 Set 集合(keySet()),通过 Set 的迭代器取出 Set 集合中的每一个元素 (Iterator)就是 Map 集合中的所有的键,再通过 get 方法获取键对应的值。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Demo2 {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "aaaa");
map.put(2, "bbbb");
map.put(3, "cccc");
System.out.println(map);
// 获取方法:
// 第一种方式: 使用keySet
// 需要分别获取key和value,没有面向对象的思想
// Set<K> keySet() 返回所有的key对象的Set集合
Set<Integer> ks = map.keySet();
Iterator<Integer> it = ks.iterator();
while (it.hasNext()) {
Integer key = it.next();
String value = map.get(key);
System.out.println("key=" + key + " value=" + value);
}
}
}
- 第二种方式:: 通过 values 获取所有值,但不能获取到 key 对象
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
46
map.put(1, "aaaa");
map.put(2, "bbbb");
map.put(3, "cccc");
System.out.println(map);
// 第二种方式:
// 通过values 获取所有值,不能获取到key对象
// Collection<V> values()
Collection<String> vs = map.values();
Iterator<String> it = vs.iterator();
while (it.hasNext()) {
String value = it.next();
System.out.println(" value=" + value);
}
}
- 第三种方式:Map.Entry
public static interface Map.Entry <K,V>
通过 Map 中的 entrySet()方法获取存放 Map.Entry<K,V>对象的 Set 集合。
Set<Map.Entry<K,V>> entrySet()
面向对象的思想将 map 集合中的键和值映射关系打包为一个对象,就是 Map.Entry ,将该对象存入 Set 集合,Map.Entry 是一个对象,那么该对象具备的 getKey,getValue 获得键和值
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "aaaa");
map.put(2, "bbbb");
map.put(3, "cccc");
System.out.println(map);
// 第三种方式: Map.Entry对象 推荐使用 重点
// Set<Map.Entry<K,V>> entrySet()
// 返回的Map.Entry对象的Set集合 Map.Entry包含了key和value对象
Set<Map.Entry<Integer, String>> es = map.entrySet();
Iterator<Map.Entry<Integer, String>> it = es.iterator();
while (it.hasNext()) {
// 返回的是封装了key和value对象的Map.Entry对象
Map.Entry<Integer, String> en = it.next();
// 获取Map.Entry对象中封装的key和value对象
Integer key = en.getKey();
String value = en.getValue();
System.out.println("key=" + key + " value=" + value);
}
}
2.6、Collections 与 Arrays
2.6.1、Conllection—>用于对数集合操作的工具类
1,对 list 进行二分查找:
前提该集合一定要有序。
int binarySearch(list,key);
//必须根据元素自然顺序对列表进行升级排序
//要求 list 集合中的元素都是 Comparable 的子类。
int binarySearch(list,key,Comparator);
2,对 list 集合进行排序。
sort(list);
//对 list 进行排序,其实使用的事 list 容器中的对象的 compareTo 方法
sort(list,comaprator);
//按照指定比较器进行排序
3,对集合取最大值或者最小值。
max(Collection)
max(Collection,comparator)
min(Collection)
min(Collection,comparator)
4,对 list 集合进行反转。
reverse(list);
5,对比较方式进行强行逆转。
Comparator reverseOrder();
Comparator reverseOrder(Comparator);
6,对 list 集合中的元素进行位置的置换。
swap(list,x,y);
7,对 list 集合进行元素的替换。如果被替换的元素不存在,那么原集合不变。
replaceAll(list,old,new);
8,可以将不同步的集合变成同步的集合。
Set synchronizedSet(Set<T> s)
Map synchronizedMap(Map<K,V> m)
List synchronizedList(List<T> list)
9. 如果想要将集合变数组:
可以使用Collection 中的toArray 方法。注意:是Collection不是Collections工具类
传入指定的类型数组即可,该数组的长度最好为集合的 size。
2.6.2、Arrays—>用于对数组操作的工具类
1,二分查找,数组需要有序
binarySearch(int[])
binarySearch(double[])
2,数组排序
sort(int[])
sort(char[])……
2,将数组变成字符串。
toString(int[])
3,复制数组。
copyOf();
4,复制部分数组。
copyOfRange():
5,比较两个数组是否相同。
equals(int[],int[]);
6,将数组变成集合。
List asList(T[]);
这样可以通过集合的操作来操作数组中元素,
但是不可以使用增删方法,add,remove。因为数组长度是固定的,会出现
UnsupportOperationExcetion。
可以使用的方法:contains,indexOf。。。
如果数组中存入的基本数据类型,那么 asList 会将数组实体作为集合中的元素。
如果数组中的存入的引用数据类型,那么 asList 会将数组中的元素作为集合中
的元素。