目录
1.认识集合
1.1集合简介
1.1.1集合框架结构图
(1)集合有两个父接口 Collection、Map
(2)Collection有两个子接口 List、set
(3)List有两个常见的实现类 ArrayList、LinkedList
(4)Set有两个常见的实现类 HashSet、TreeSet
(5)Map有两个常见的实现类 HashMap、HashTable
1.1.2不同集合的特点
(1)List 特点:有序、可重复
(2)Set 特点:无序、不可重复
(3)Map 特点:无序,不可重复,存放【键值对】(key 键 -- value 值)
1.2List接口
1.2.1 ArrayList与LinkedList
ArrayList:是基于动态数组的数据结构,搜索效率相对高,修改效率相对低
LinkedList:是基于链表的数据结构搜索效率相对低,修改效率相对高
对于随机访问set和get,ArrayList优于LinkedList,因为LinkedList需要迭代器(需要从前往后遍历)
对于插入和删除操作,LinkedList优于ArrayList,因为ArrayList需要移动数据。
对于ArrayList来说add是直接插入队尾的并不需要移动元素(追加),就算加上扩容的代价,平均add效率也远高于LinkedList,所以LinkedList只在中间元素的插入和删除效率上有优势
ArrayList的空间浪费体现在,在列表的结尾预留一定的容量空间,LinkedList的空间浪费主要体现在它的每一个元素都需要消耗相当的空间。
1.2.2 List接口下的常用方法
(1)add(o)方法,在末尾添加一个对象
(2)add(int index,o),在指定索引位插入一个对象
(3)set(int index,o),将指定索引位
(4)get(int index),返回指定索引位的对象
(5)remove(int index),删除指定索引位的对象并返回它
(6)remove(o),删除第一个指定的对象,返回值为布尔类型,表示是否删除成功
(7)contains(o),判断是否存在指定的对象,返回值为布尔类型
(8)size(),返回List包含的元素个数(int类型)
(9)indexOf(o),返回该元素的第一个索引值,没有返回-1
(10)clear(),清空List
ArrayList list = new ArrayList();
list.add("张三丰");//添加一个对象到集合中
list.add(1);
list.add(2.333);
System.out.println(list);
System.out.println(list.contains("张三丰"));//判断是否包含"张三丰"字符串对象
System.out.println(list.contains(1));
System.out.println("-------------------------------");
list.remove(0);//删除索引值为0位置上的对象
System.out.println(list.contains("张三丰"));//张三丰在0的位置上,被删除了
System.out.println("-------------------------------");
list.remove((Object)1);//删除对象1
System.out.println(list.contains(1));
System.out.println();
list.add("土豆片");
list.add(1,"西瓜皮");//在指定位置插入一个新的对象
for (int i = 0; i < list.size(); i++) {//size()方法返回集合中对象的个数
System.out.println(list.get(i).toString());//get方法获取i索引值上的对象
}
System.out.println("--------------------------------");
list.set(1,"黄蓉");//在索引为值为1的位置上用"黄蓉"字符串替换原来的内容
for (int i = 0; i < list.size(); i++) {//size()方法返回集合中对象的个数
System.out.println(list.get(i).toString());//get方法获取i索引值上的对象
}
System.out.println("---------------------------");
System.out.println(list.indexOf("小龙女"));//不存在,返回-1
System.out.println(list.indexOf("黄蓉"));//返回1
System.out.println("----------清空----------");
list.clear();//清空list
for (Object obj: list ) {
System.out.println(obj.toString());//可以使用foreach遍历集合
}
System.out.println("----------清空----------");
1.2.3LinkedList的额外方法
主要是在开头和末尾添加值,以及删除开头和末尾的值的方法。
addFirst(o),addLast(o),removeFirst(),removeLast()
List list = new LinkedList();
boolean a =list.add(false);//此方法有返回值
System.out.println(list);
System.out.println(a);
((LinkedList) list).addFirst("111");//在首部加入元素
for (Object i:list
) {
System.out.println(i.toString());
}
((LinkedList) list).addLast("123");//在尾部加入元素,这个方法没有返回值
1.3Set接口
1.3.1HashSet
HashSet堪称查询速度最快的集合,因为其内部是以HashCode来实现的。集合元素可以是null,但只能放入一个null。它内部元素的顺序是由哈希码来决定的,所以它不保证set的迭代顺序;特别是它不保证该顺序恒久不变。线程不安全的,无序
HashSet的常用方法
(1)add(o),添加一个对象,如果此操作改变了集合,会返回true,否则返回false
(2)其他的方法如remove(o),clear(),size(),contains()都与List的方法一样
1.3.2TreeSet
TreeSet是二叉树实现的,基于TreeMap,生成一个总是处于排序状态的set,内部以TreeMap来实现,不允许放入null值。它是使用元素的自然顺序对元素进行排序,或者根据创建Set时提供的 Comparator 进行排序,具体取决于使用的构造方法。线程不安全的,有序。
1.3.3LinkedHashSet
LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。
1.4Map
HashMap的常用方法
(1)put(key,value),添加一个键值对,返回null,key和value都是Object,如果已经存在key,则更改value为新的值并将其返回
(2)get(key),返回key对应的value,如果没有,返回null
(3)remove(key),删除相应的键值对,返回删除掉的value,如果没有返回null
(4)containsKey(key),containsValue(value),返回值为boolean类型
(5)size(),返回包含的键值对数量
(6)keySet(),返回包含所有key值的Set集合
(7)values(),返回包含所有value值的Collection集合
Map map = new HashMap();
Object a = map.put(1,"南瓜");//添加,不存在value,返回值为null
System.out.println(a);//null
Object b = map.put(1,"土豆");//添加,已存在,替换并返回被替换的值
System.out.println(b);//"南瓜"
System.out.println(map);
System.out.println("-------------------------");
a = map.remove(2);//删除一个键值对,参数为key,如果没有对应的键值对,返回null
System.out.println(a);//null
b = map.remove(1);//如果有对应的键值对,返回其value
System.out.println(b);
System.out.println("-------------------------");
map.put(1,"南瓜");
a = map.get(1); //返回与key对应的value
System.out.println(a);//"南瓜"
b = map.get(2);//如果没有该键值对,返回null
System.out.println(b);//null
System.out.println("--------------------------");
System.out.println(map.containsKey(1));//true,判断是否存在该key
System.out.println(map.containsKey(2));//false
System.out.println("-------------------------");
System.out.println(map.containsValue(1));//false,判断是否存在该value
System.out.println(map.containsValue("南瓜"));//true
System.out.println("-------------------------");
System.out.println(map.isEmpty());//false,判断是否空
System.out.println("----------------------------");
System.out.println(map.size());//1,返回元素数量(键值对)
System.out.println("----------------------------");
map.put("土豆","999");
Set set = map.keySet();//返回键值集合
Iterator it = set.iterator();
while(it.hasNext()){
System.out.println(it.next().toString());
}
System.out.println("-----------------------------");
Collection collection = map.values();//返回value集合的Collection对象
System.out.println(collection);
for (Object i : collection) {
System.out.println(i.toString());
}
System.out.println("-------------------------------");
for (Object s:map.keySet()) {
System.out.println(s);
System.out.println(map.get(s));
}
2.遍历集合的方法
2.1Iterator接口
每个Collection类的对象都要实现Iterator接口下约定的iterator()方法,这个方法实际上是返回一个集合的迭代器,用于遍历集合,Iterator主要带有两个方法hasNext()和next()方法。
hasNext()方法是判断集合中是否存在下一个元素,返回值为布尔值类型
next()方法是返回下一个元素的值
一般采用while循环的方式,当hasNext()为true时,将下一个元素的值返回出来,如果为false则退出循环。
2.1.1HashSet集合使用Iterator示例
Set s = new HashSet();
s.add("123");
s.add("111");
Iterator its = s.iterator();//集合对象自带iterator()方法,并返回一个Iterator类型的对象
while(its.hasNext()){
System.out.println(its.next());
}
/*
*结果为
123
111
*/
2.1.2HashMap集合使用Iterator示例
HashMap map = new HashMap();
map.put("姓名","张三");
map.put("年龄","22");
Set s = map.keySet();
Iterator its = s.iterator();//获得keySet的迭代器
while(its.hasNext()){
String key = its.next().toString();//next()得到的是Object类型,转换为String
System.out.print("key=" + key);//输出key值
System.out.println(",value="+map.get(key));//根据key值,使用get方法获得value值
}
/*
结果为
key=姓名,value=张三
key=年龄,value=22
*/
2.2foreach循环遍历
2.2.1ArrayList使用foreach循环遍历示例
List list = new ArrayList();
list.add("1234");
list.add(-1);
list.add("abcd");
for (Object i: list) {
System.out.println(i.toString());
}
/*
结果为
1234
-1
abcd
*/
2.2.2HashMap使用foreach循环遍历示例
Map map = new HashMap();
map.put("姓名","张三");
map.put("年龄","22");
for (Object i :map.keySet()) {
String key = i.toString();
System.out.print("key="+key);
System.out.println("value="+map.get(key));
}
//结果与使用Iterator接口的遍历是一样的
2.3普通for循环
普通for循环只能对有序的集合进行遍历,也就是ArrayList和LinkedList,下面以LinkedList为例,方法与普通数组一样,只不过需要将length属性改为size()方法
List list = new LinkedList();
list.add("gggg");
list.add("haha");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
/*
结果为
gggg
haha
*/
3.泛型
集合中使用泛型规定了集合中每个元素的类型为规定好的同一类型,使用方法为<数据类型>,我们在平常使用集合时,尽管可以不使用泛型限定添加的类型,但太过随意的添加任意类型的值会导致集合可能产生数据类型的污染,并且在使用一些方法时可能会有数据类型参数的不匹配而导致异常,因此在使用集合时,必须要加上泛型对其中元素的类型进行限定。
List<String> list1 = new ArrayList<String>();//前后都要使用泛型标识符
List<String> list2 = new LinkedList<>();//后面<>内的内容可以省略