集合
What is Collection used for?
对象用于封装特有数据,对象需要被存储,如果对象的个数不确定,就需要使用集合来进行存储
集合的特点:
1.用于存储对象的容器
2.集合的长度是可变的
3.集合中不可以存储基本数据类型值
Collection
集合因为内部的数据结构不同,所以存在着多种集合。不断地将集合的共有的功能向上抽取,就形成了集合框架
框架的顶层Collection接口:
1.增加
boolean add(E e)
boolean addAll(Collection<? extends E> c)//将指定集合中的所有元素添加到该集合
2.删除
void clear()//从此集合中删除所有元素
boolean remove(Object o)//从该集合中删除指定元素的单个实例(如果存在)
boolean removeAll(Collection<?> c)//删除指定集合中包含的所有此集合的元素(可选操作)
3.判断
boolean contains(Object o)//如果此集合包含指定的元素,则返回 true
boolean containsAll(Collection<?> c)//如果此集合包含指定 集合中的所有元素,则返回true
boolean isEmpty()//判断集合是否为空
4.获取
int size()//获取集合长度
Iterator<E> iterator()//去除元素的方式:返回此集合中的元素的迭代器
迭代器对象必须依赖于具体容器,因为每一个容器的数据结构都不同,所以该迭代器对象是在容器内部进行实现的。所以对于容器使用者而言,具体的实现不重要,只要通过容器获取到该实现的迭代器的对象即可
就是iterator方法
Iterator接口就是对所有的Collection容器进行元素取出的公共接口
5.其他方法
boolean retainAll(Collection<?> c)//仅保留此集合中包含在指定集合中的元素(取交集)
Object[] toArray()//返回一个包含此集合中所有元素的数组
迭代器的使用:
Collection c = new ArrayList();
c.add("1");
c.add("2");
c.add("3");
c.add("4");
System.out.println(c);
Iterator<String> it = c.iterator();
//hasNext:是否还有元素可以迭代(有:true,无:false)
while(it.hasNext()) {
//next:返回迭代中的下一个元素
System.out.println(it.next());
}
result:
[1, 2, 3, 4]
1
2
3
4
List和Set
List:有序(存入和取出的顺序一致),元素都有索引,允许重复的元素
1.添加
boolean add(E e)//将指定的元素追加到此列表的末尾
void add(int index, E element)//将指定的元素插入此列表中的指定位置
2.删除
E remove(int index)//删除该列表中指定位置的元素
boolean remove(Object o)//从列表中删除指定元素的第一个出现
3.修改
E set(int index, E element)//用指定的元素(可选操作)替换此列表中指定位置的元素
4.获取
E get(int index)//返回此列表中指定位置的元素
int indexOf(Object o)//返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1
int lastIndexOf(Object o)//返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1
List<E> subList(int fromIndex, int toIndex)//返回此列表中指定的 fromIndex(含)和 toIndex之间的 视图(左闭右开)
迭代器:ListIterator
常用子类:
1.Vector:内部是数组,同步
2.ArrayList:内部是数组,非同步,替代了Vector
数组长度不可变,如果要可变,需要创建新数组再插入
3.LinkedList:内部是链表,非同步
…
上面数组和链表的优缺点和数据结构的一样
分插入和删除
Set:无序,不允许重复的元素
1.HashSet:内部是哈希表,非同步
哈希表确定元素是否相同是判断两个元素的哈希值是否相同,如果相同,再判断两个对象的内容是否相同
判断哈希值相同使用的是对象的hashCode方法,判断内容相同,用的是equals方法,如果哈希值不同,就不需要判断equals了
2.LinkedHashSet:哈希表和链表实现了Set接口,具有可预测的迭代次序。 这种实现不同于HashSet,它维持于所有条目的运行双向链表。非同步
3.TreeSet:底层使用红黑树,可以对Set集合中的元素进行排序,非同步
如果需要排序,元素就实现compareTo接口
…
看到array:就要想到数组,查询快,有索引
看到link:就要想到链表,增删快,有add get remove(first|last)
看到hash:就要想到哈希表,有唯一性,元素需要覆盖hashcode和equals方法
看到tree:就要想到二叉树,排序,就要想到两个接口:Comparable,Comparator
Map
一次添加一个键值对
Map中不能包含重复的建,每个键可以映射到最多一个值
常用方法:
1.增加
V put(K key, V value)//返回前一个和key关联的值,如果没有就返回null
2.删除
void clear()//清空map
V remove(Object key)//如果存在(从可选的操作),从该map中删除一个键的映射
3.判断
boolean containsKey(Object key)//如果此映射包含指定键的映射,则返回 true
boolean containsValue(Object value)//如果此map将一个或多个键映射到指定的值,则返回 true
boolean isEmpty()//如果此地图不包含键值映射,则返回 true
4.获取
V get(Object key)//返回到指定键所映射的值,或通过返回null来判断是否包含某个键
int size()//返回此地图中键值映射的数量
重点方法:
Set<K> keySet()//返回此map中包含的键的Set视图
取出map中的所有元素的方法:
通过keySet方法获取map中所有的键的Set集合,再通过Set的迭代器获取到每一个键,然后再用键来取值
Set<Map.Entry<K,V>> entrySet()//返回此map中包含的映射的Set视图
通过将map转换成Set就可以进行迭代,那么就可以使用entrySet方法来获取,将键值对的映射关系作为对象存储到了Set集合中,这个映射关系的类型就是Map.Entry<K,V>
Collection<V> values()//返回此map中包含的值的Collection视图
常见子类对象
1.Hashtable:内部是哈希表,同步,不允许null作为键或值
Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合
2.HashMap:内部是哈希表,不同步,允许null作为键或值
3.TreeMap:内部是二叉树,不同步,可以对Map集合中的键进行排序
泛型
好处:
1.将运行时期的问题ClassCastException转到了编译时期
2.避免了强制转换的麻烦
当操作的引用数据类型不确定的时候,使用<>将数据类型传入。
泛型技术是给编译器使用的技术,用于编译时期,确保了类型的安全
泛型的擦除:运行时,会将泛型去掉,生成的class文件中是不带泛型的
为什么擦除呢:因为为了兼容运行的类加载器
泛型的补偿:在运行时,通过获取元素的类型进行转换动作,不需要使用者再进行强制转换了
泛型类
使用泛型来接收类中药操作的引用数据类型
当类中的操作的引用数据类型不确定的时候,就用泛型来表示
class Tool<QQ>{
}
泛型方法
public <QQ> void tool(QQ qq){
}
public void tool(QQ qq){
}
//静态方法使用泛型,必须在方法定义出泛型 放在返回值的前面,修饰符的后面
public static <QQ> void tool(QQ qq){
}
泛型接口
interface Tool<T>{
public void shou(T t);
}
class ToolImpl1 implements Tool<String>{
public void show(String str){
System.out.prinln("show:"+str);
}
}
class ToolImpl2<Q> implements Tool<Q>{
public void show(Q q){
System.out.prinln("show:"+q);
}
}
//使用
public static void main(String[] args){
ToolImpl2<Integer> in = new InterImpl2<Integer2>();
in.show(5);
}
集合查阅的技巧
需要唯一吗?
需要:Set
需要指定顺序吗?
需要:TreeSet
不需要:HashSet
但是想要一个和存储一致的顺序(有序):LinkedHashSet
不需要:List
需要频繁增删吗?
需要:LinkedList
不需要:ArrayList
如何记录每一个容器的结构和所属体系呢?
看名字
List
|–ArrayList
|–LinkdeList
Set
|–HashSet
|–TreeSet
Foreach循环遍历集合
for(类型 变量名 : Collection集合){
}
这种遍历方式,有一定的局限性,只能遍历,无法对集合中的元素进行操作
遍历Map的时候,需要将map转换成set
for(类型 变量名 : map.keySet()){
}
for(Map.Entry<A, B> me : map.entrySet()){
}
函数可变参数
调用: newAdd(5, 1, 2, 3) 或者 newAdd(5)…
public static int newAdd(int … arr){
}