集合类(集合框架)
为什么出现:
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一中方式。
数组和集合类同是容器,有何区别
数组长度是固定的,集合长度是可变的
数组只能存储一种类型的对象,集合可以存储不同类型的对象
数组可以存储基本数据类型 集合自能存储对象
特点
集合只用于存储对象,集合长度可变,集合可以存储不同类型的对象
集合中存储的都是对象的引用(地址);
Collection
---List 元素是有序的,元素可以重复,因为该集合体系有索引
--- ArrayList
--- LinkedList
--- Vector
---Set 元素是无序的,元素不重复。
---HashSet
---TreeSet
为什么出现这么多的容器
因为每一个容器对数据的存储方式都不同,这个存储方式可以称之为:数据结构
ArrayList al = new ArrayList();
添加元素 add();
获取长度 size();
删除元素 remove(); clear();清空
判断元素 contains();是否存在 isEmpty();
交集 retainAll(); 只会取一样的元素
Iterator迭代器接口
集合的取出元素的方式;
接口下的方法 next()去出下一个元素
hasNext() 如果有元素返回真没有返回假。
方法一
Iterator it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
方法二
for(Iterator it = list.iterator(); it.hasNext(); )
System.out.println(it.next());
迭代器的特点:
List集合共性方法 凡是可以操作角标的都是该体系特有的方法
add(int index E e)在指定位置插入元素
remove()删除
get(int index)索引获取
indexOf()判断元素位置
listIterator()有序的返回该迭代器元素
set(int index E e)修改 改变一个位置上的元素
subList()包含头不包含尾
List特有的获取所有元素的方法-- - 通过角标
for(int x=0; x<list.size();x++ )
System.out.println(list.get(x));
List集合特有的迭代器 ListIterator是Iterator 的子接口
在迭代时,不可以通过集合对象的方法操作集合中的元素
因为会发生异常
所以,在迭代器时,只能用迭代器的方法操作元素,所以Iterator方法是有限的
只能对元素进行判断,取出,删除操作。所以想要其他的操作如添加修改,就需要用的起子接口listIterator()
--- ArrayList 底层的数据结构使用的数组结构 特点:查询速度很快,增加删除较慢
--- LinkedList 底层使用的是链表数据结果 特点:查询很慢,增加删除速度快
--- Vector 底层是数组数据结构。 特点:增删 查询都慢
Vector(1.0版本)和ArrayList(1.2版本)区别
1. ArrayList线程不同步(查询速度很快,增加删除较慢),Vector 线程同步(增删查询都慢)
2. ArrayList和Vector底层都是数组结果,数组长度是不可变的,但身为集合长度是可变的,所以ArrayList和Vector的默认长度都是长度为10的空列表,但当数据超过容量后,ArrayList会以50%延长变为15,把原来的数据拷贝过来,并在后面加新的数据。而Vector100%延长
枚举 Enumeration
Vector中有个方法elements()返回的是Enumeration类型
public Enumeration<E> elements()
枚举就是Vectore特有的取出方式 :迭代器,遍历while, for()循环。按角标索引,枚举
其实枚举和迭代是一样的,因为枚举的名称和方法的名称都过长,所以都被迭代器取代了
之所以还用枚举是因为,IO中有个对象用到枚举了
LinkedList
特有方法
addFirst(); addLast()
getFirst(); getLast() 获取元素,但元素不删除
removeFirst(); removeLast() 获取元素,但元素被删除
因为如果集合中没有元素,则会出现NoSuchElementException异常
LinkedLIst特有的取出方式
while(!list.isEmpty()){
System.out.println(list.removeFirst());
}
堆栈:先进后出 队列:先进先出
---HashSet 数据结构是哈希表
---TreeSet 可以对Set集合中的元素进行排序
HashSet 复写hashCode()和equals方法
public int hashCode() {
return name.hashCode() + age;
}
public boolean equals(Object obj) {
if (!(obj instanceof Student)){
return false;
}
Student s = (Student)obj;
return this.name.equals(s.name) && this.age == s.age;
}
TreeSet 可以对Set集合中的元素进行排序
import java.util.*;
public class TreeSetDemo {
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet hs = new TreeSet(new MyComp());
hs.add(new PersonDemo("a1",20));
hs.add(new PersonDemo("lisi",22));
hs.add(new PersonDemo("wangwu",24));
hs.add(new PersonDemo("abc",21));
hs.add(new PersonDemo("abc",21));
for(Iterator it = hs.iterator(); it.hasNext();){
PersonDemo p = (PersonDemo) it.next();
System.out.println("Name="+p.getName()+"...Age="+p.getAge());
}
}
}
//集合具备比较
class MyComp implements Comparator{
@Override
public int compare(Object o1, Object o2) {
// TODO Auto-generated method stub
PersonDemo pd1 = (PersonDemo)o1;
PersonDemo pd2 = (PersonDemo)o2;
int num = new Integer(pd1.age).compareTo(new Integer(pd2.age));
if(num ==0)
return pd1.name.compareTo(pd2.name);
return num;
}
}
//元素自身具备比较性
class PersonDemo /*implements Comparable*/{
String name;
int age;
PersonDemo(String name,int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/* @Override
public int compareTo(Object obj) {
// TODO Auto-generated method stub
if(!(obj instanceof PersonDemo)){
System.out.println("不是人");
}
PersonDemo pd = (PersonDemo)obj;
int num = new Integer(this.age).compareTo(new Integer(pd.age));
if(num ==0)
return this.name.compareTo(pd.name);
return num;
}
*/
}
泛型 <>
JDK1.5出现的 用于解决安全问题,是一个安全机制。
在定义集合的时候就明确里面装什么类型
1.将运行时期出现的问题ClassCastException转移到编译时期。
2.避免了强制转换的麻烦。
格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候写泛型呢。
通常在
集合框架中很常见,只要见到<>就要定义泛型
泛型类
泛型方法
Public <T> void show(T t)
特殊之处:静态方法不可以访问类上定义的泛型,如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上
泛型定义在接口上
Interface infer<T> {}
取所有的键值
必须保证两边类型一样,如果不一样用的泛型限定
ArrayList<? ExtendsPerson>
?通配符,也可以理解为占位符。
泛型的限定
向上限定 ? ExtendsE 。可以接受E类型或者E的子类型
向下限定 ? super E 可以接受E类型或者E的父类型
Map集合 <K,V> 存储键和值,每个键最多只能映射到一个值
将键映射到值的对象,一个映射不能包含重复的键
---HashTable底层是哈希表数据结构,不可以存入null键null值,线程同步
---HashMap 底层是哈希表数据结构,可以存入null键null值,线程不同步
---TreeMap 底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序,和Set很像。其实Set底层就是使用了Map集合
1 添加
put(key , value) 当存入相同键的时候,新的值会替换老的值
2 删除
clear()全部删除
remove(key)删除键
3 判断
containKey()判断键 返回 true。
containValue()判断值 返回 true。
isEmpty()返回 true。
4 获取
get(Objectkey)获取键返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回null
values()获取集合中所有的值
Map集合的取出方式
keyset() 获取所有的键 将map中所有的键存入到set集合,因为set具备迭代器,所以可以迭代方式取出所有的键,再根据get方法,获取每一个键对应的值
//定义HashMap集合
HashMap<String, String> hm = new HashMap();
//将对象添加到集合中
hm.put("03", "zhangsan");
hm.put("04", "lisi");
hm.put("05", "wangwu");
//先获取Map集合中所有键的值,存储到Set集合中
Set<String> s = hm.keySet();
//调用Set集合的迭代器
Iterator<String> it = s.iterator();
while(it.hasNext()){
//通过Set集合 -------获取所有的键
String key = it.next();
//通过Map集合 --------获取所有的值
String value = hm.get(key);
System.out.println(key + "::" + value);
}
entrySet()将Map集合中的映射关系存入到Set集合中,而这个关系的数据类型就是Map.Entry
HashMap<String, String>hm = new HashMap();
hm.put("03", "zhangsan");
hm.put("04", "lisi");
hm.put("05", "wangwu");
Set<Map.Entry<String, String>> s = hm.entrySet();
Iterator<Map.Entry<String, String>> it =s.iterator();
while(it.hasNext()){
Map.Entry<String, String> m = it.next();
String key = m.getKey();
String value = m.getValue();
System.out.println(key+"::"+value);
Map.Entry 其实Entry也是一个接口,是Map中的一个内部接口
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
HashMap<String,Student> hm = new HashMap<String,Student>();
hm.put("shandong",new Student("zhangsan","20"));
hm.put("qinghai",new Student("lisi","25"));
hm.put("xizhang",new Student("wangwu","25"));
/* //取出方式一 KeySet
Set<String> l = hm.keySet();
Iterator<String> it = l.iterator();
while(it.hasNext()){
String add = it.next();
Student sd = hm.get(add);
System.out.println(add+":"+sd);
}*/
//取出方式二 EntrySet
Set<Map.Entry<String, Student>> s = hm.entrySet();
Iterator<Map.Entry<String, Student>> it =s.iterator();
while(it.hasNext()){
Map.Entry<String, Student> m = it.next();
String add = m.getKey();
Student sd = m.getValue();
System.out.println(add+":"+sd);
}
}
}
对学生对象的年龄进行排序 按照姓名排序,如果姓名相同则按照年龄排序
class StuNameComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
// TODO Auto-generatedmethod stub
int num = o1.getname().compareTo(o2.getname());
if(num==0){
return o1.getage().compareTo(o2.getage());
}
return num;
}
}
子母出现的次数
public static String charCount(String str){
//将字符串转换为字符数组,因为要的每一个字符进行操作
char[] ch = str.toCharArray();
//定义一个map集合,因为打印的子母,有序。所以用TreeMap
TreeMap<Character,Integer> tm =
newTreeMap<Character,Integer>();
//遍历字符数组
int count = 0;//定义在外面,避免一次一次的开辟空间
for(int x=0;x<ch.length; x++){
//将每一个子母作为键去查集合
Integer value = tm.get(ch[x]);
if(value!=null)
count = value;
count++;
tm.put(ch[x], count);
count = 0;
/*
//如果返回空,则将子母和1存入map集合
if(value==null)
tm.put(ch[x], 1);
else{//如果不是空,则已经存在,那么获取该次数并且自增
value = value + 1;
tm.put(ch[x], value);
} */
}
StringBuilder sb = new StringBuilder();
Set<Map.Entry<Character,Integer>> s =tm.entrySet();
Iterator<Map.Entry<Character,Integer>> it =s.iterator();
while(it.hasNext()){
Map.Entry<Character,Integer> m = it.next();
Character c = m.getKey();
Integer in = m.getValue();
System.out.print(c+"{"+in+"}");
}
return sb.toString();
}
Map扩展
一对多的映射关系
方法一:
public class MapExpandDemo {
//一对多:man “01”“zhangsan” ,“02”“lisi”
// woman “03”“zhanghong” “04”“hanmei”
/**
* @param args
*/
public static void main(String[] args) {
HashMap<String,String> boy = new HashMap<String,String>();
boy.put("01", "zhangsan");
boy.put("02", "lisi");
HashMap<String,String> girl = new HashMap<String,String>();
girl.put("03", "zhanghong");
girl.put("04", "hanmei");
HashMap<String,HashMap<String,String>> per = newHashMap<String,HashMap<String,String>>();
per.put("man",boy);
per.put("woman",girl);
Iterator<String> it = per.keySet().iterator();
while(it.hasNext()){
String sex = it.next();
HashMap<String,String> hm = per.get(sex);
System.out.println(sex);
getPerInfor(hm);
}
}
public static void getPerInfor(HashMap<String,String> pers){
Iterator<String> it = pers.keySet().iterator();
while(it.hasNext()){
String id = it.next();
String name = pers.get(id);
System.out.println(id+":::"+name);
}
}
}
方法二
public class MapExpandDemo2 {
// mannew Student(“01”“zhangsan”) ,new Student(“02”“lisi”)
// woman new Student(“03”“zhanghong”) new Student(“04”“hanmei”)
//将ID号和名称看着一个对象
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
List boy = new ArrayList<Student>();
List girl = new ArrayList<Student>();
boy.add(new Student("01","zhangsan"));
boy.add(new Student("02","lisi"));
girl.add(new Student("03","zhanghong"));
girl.add(new Student("04","hanmei"));
HashMap<String,List<Student>> hm = newHashMap<String,List<Student>>();
hm.put("man", boy);
hm.put("woman", girl);
Iterator <String> it = hm.keySet().iterator();
while(it.hasNext()){
String sex = it.next();
List <Student> st = hm.get(sex);
System.out.println(sex);
getPerInfor(st);
}
}
public static void getPerInfor(List<Student> std){
Iterator<Student> it = std.iterator();
while(it.hasNext()){
Student id = it.next();
System.out.println("<"+id+">");
}
}
}
Collections 作为工具类里面的方法是静态的
专门对集合操作的工具类
Sort方法
public static <T extends Comparable<? super T>> voidsort(List<T> list)
根据元素的自然顺序对指定列表按升序进行排序。
List<String> l = new ArrayList();
l.add("abgsg");
l.add("egrsg");
l.add("bsg");
l.add("kesg");
System.out.println(l);
Collections.sort(l);
System.out.println(l);
按照长度排列
public class SortDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generatedmethod stub
List<String> l = new ArrayList();
l.add("abgsg");
l.add("egrsg");
l.add("bsg");
l.add("kesg");
System.out.println(l);
Collections.sort(l,new legCom());
System.out.println(l);
}
}
class legCom implements Comparator<String>{
@Override
public int compare(String s1,String s2) {
// TODO Auto-generatedmethod stub
if(s1.length()<s2.length())
return -1;
if(s1.length()>s2.length())
return 1;
return s1.compareTo(s2);
}
}
max方法 按照顺序。返回collection中最大的元素
Collections.sort(l,new legComp());
System.out.println(l);
String c = Collections.max(l,new legComp());
System.out.println(c);
输出结果
[bsg, kesg, abgsg, egrsg]
egrsg
binarySearch
public static <T> int binarySearch(List<? extendsComparable<? super T>> list, T key)
使用二分搜索法搜索指定列表,以获得指定对象。
如果搜索键包含在列表中,则返回搜索键的索引;否则返回(-(插入点) - 1)。
fill
public static <T> void fill(List<? superT> list,T obj)
使用指定元素替换指定列表中的所有元素。
replaceAll
public static <T> boolean replaceAll(List<T> list,T oldVal,T newVal)
使用另一个值替换列表中出现的所有某一指定值
reverse(List<?> list)
反转指定列表中元素的顺序。
reverseOrder()
返回一个比较器,它强行逆转实现了 Comparable 接口的对象collection 的自然顺序。
Arrays用于操作数组的工具类 里面都是静态方法
把数组变成集合asList() 好处,可以使用集合的思想和方法来操作数组中的元素
注意:将数组变成集合,不可以使用集合的增删方法。因为数组长度是固定的
String [] arr = {"saa","gewas","agh"};
//把数组变成集合
List<String> l = Arrays.asList(arr);
System.out.println(l);
如果数组中的元素都是对象,那么变成集合时,数组中的元素就会直接转成集合中的元素
如果数组中的元素是基本类型。那么会将该数组作为集合中的元素存在
int [] num = {1,2,3,4};
List<int[]> l = Arrays.asList(num);
System.out.println(l);
结果为 [[I@1fc4bec]
集合转换成数组
Collection接口中的toArray()
ArrayList<String> al = new ArrayList<String>();
al.add("ash");
al.add("aagbh");
al.add("aabgsabg");
String [] a = al.toArray(new String[5]);
System.out.println(a);
System.out.println(Arrays.toString(a));
结果
[Ljava.lang.String;@18a992f
[ash, aagbh, aabgsabg, null, null]
1. 指定类型的数组到底要定义多长呢。
当指定类型的数组长度小于集合的size,那么该方法内部会创建一个新的数组
当当指定类型的数组长度大于集合的size,就不会心创建数组。
所以创建一个刚刚好的数组最优
2. 为什么要讲集合变数组
为了限定对元素的操作
增强for循环
格式:
for(数据类型 变量名 :被遍历的集合或者数组){}
for(Strings : list){}
可变参数
就是数组参数的简写形式
public static void show(int… arr){
system.out.println(arr);
}