------- android培训、java培训、期待与您交流!----------
面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。
集合与数组的异同:
容器长度:
集合长度可变
数组长度固定
存储内容类型:
集合存储引用数据类型
数组存储任意类型
是否可存储不同类型数据:
集合可以存储不同类型数据
集合概述数组只能存储相同数据类型
Java中的集合:
JDK为我们提供了一套完整的容器类库,这些容器可以用于存储各种类型的对象,并且长度都是可变的,我们把这些类统称为集合类,它们都位于java.util包中。
分类:
单列集合Collection
List:元素有序、包含重复元素
Set:元素无序、不包含重复元素
双列集合Map:
键值映射关系
其他功能接口:
迭代器Iterator
Comparable与Comparator用于比较元素
集合——Collection:单列集合的根接口
Collection
List
ArrayList:
底层数据结构是数组,查询快,增删慢;
线程不安全,效率高
Vector:
底层数据结构是数组,查询快,增删慢;
线程安全,效率低
LinkedList:
底层数据结构是链表,查询慢,增删快;
线程不安全,效率高
Set
HashSet:
底层数据结构是哈希表
如何保证其唯一性:
依赖hashCode()和equals()
先判断hashCode()值是否相同;如果相同就看equals(),看返回值。如果是true,就是元素重复,不添加;如果是false,就是元素不重复,添加。
TreeSet:
底层数据结构是二叉树;
如何保证其唯一性:
根据返回值是否是0;
如何排序:
自然排序:Comparable
比较器排序:Comparator
LinkedHashSet:
底层数据结构是链表和哈希表;
由链表保证有序(存储和去除一致);
由哈希表保证元素唯一。
主要方法:
boolean add(E e) 添加元素 返回值类型表示:添加是否成功
代码实现:
package cn.itcast2; import java.util.ArrayList; import java.util.Collection; public class Demo2 { public static void main(String[] args) { //创建集合对象 Collection c = new ArrayList(); //准备元素 int luckyNumber = 13; String myWords = "休息时候十个小时都用到!"; Student s = new Student("刘亦菲",27); //将元素放到集合中 c.add(luckyNumber); c.add(myWords); c.add(s); //遍历集合 System.out.println(c); } }
boolean remove(Object o) 删除指定元素
该方法在删除元素时,会调用实参的equals方法,与老元素比较,如果相同则删除,否则不删除。
代码实现:
package cn.itcast2; import java.util.ArrayList; import java.util.Collection; public class Demo3 { public static void main(String[] args) { //创建集合对象 Collection c = new ArrayList(); //准备元素 int luckyNumber = 13; String myWords = "休息时候十个小时都用到!"; Student s = new Student("刘亦菲",27); //将元素放到集合中 c.add(luckyNumber); c.add(myWords); c.add(s); //遍历集合 System.out.println(c); // c.remove(s); c.remove(new Student("刘亦菲",27)); System.out.println(c); }
void clear() 清空
boolean contains(Object o) 如果此 collection 包含指定的元素
boolean isEmpty() 判断是否为空
int size() 判断容器内已经存在的元素个数
代码实现:
package cn.itcast2; import java.util.ArrayList; import java.util.Collection; public class Demo4 { public static void main(String[] args) { //创建集合对象 Collection c = new ArrayList(); //准备元素对象 Integer number = new Integer(13); Integer number2 = new Integer(2); Integer number3 = new Integer(250); //将元素添加到集合 c.add(number); c.add(number2); c.add(number3); //遍历集合 System.out.println(c); boolean contains = c.contains(250); System.out.println(contains); System.out.println(c.isEmpty()); System.out.println(c.size()); System.out.println("===================================="); c.clear(); System.out.println(c.size()); System.out.println(c.isEmpty()); System.out.println(c); } }
boolean retainAll(Collection c) 仅保留此 collection 中那些也包含在指定 collection 的元素,即求交集
代码实现:
package cn.itcast2; import java.util.ArrayList; import java.util.Collection; public class Demo6 { public static void main(String[] args) { Collection c = new ArrayList(); Collection c2 = new ArrayList(); c.add("baby"); c.add("宝强"); c.add("祖蓝"); c.add("邓超"); c.add("大黑牛"); c2.add("宝强"); c2.add("祖蓝"); c2.add("大黑牛"); // c2.add("何炅"); System.out.println(c); System.out.println(c2); System.out.println(c.retainAll(c2)); System.out.println(c); Collection c3 = new ArrayList(); System.out.println(c.retainAll(c3)); System.out.println(c); } }
单列集合迭代器方法:
Iterator iterator() 返回在此 collection 的元素上进行迭代的迭代器。
迭代器:用来迭代的工具,用来遍历集合的工具。
迭代器的方法:
boolean hasNext() 如果仍有元素可以迭代,则返回 true。
集合中存储的数据类型 next() 返回迭代的下一个元素。 默认是Object。
代码实现:
package cn.itcast2; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Demo7 { public static void main(String[] args) { //创建集合对象 Collection c = new ArrayList(); //准备元素对象 String name = "卢俊义"; String name2 = "宋江"; String name3 = "扈三娘"; String name4 = "孙二娘"; String name5 = "顾大嫂"; //将元素放入到集合 c.add(name); c.add(name2); c.add(name3); c.add(name4); c.add(name5); //迭代集合(遍历集合) //a:产生该集合的迭代器 Iterator i = c.iterator(); //b:调用迭代器的方法,遍历集合 while(i.hasNext()) { Object next = i.next(); String sNext = (String)next; System.out.println(sNext); } System.out.println("获取完了!");
}
}
List接口:单列集合,可存放重复元素,元素有序。
ArrayList:底层数据结构是数组结构。线程不安全的。所以ArrayList的出现替代了Vector。增删慢,改查快。
LinkedList:底层是链表数据结构。线程不安全的,同时对元素的增删操作效率很高。
Vector:底层数据结构是数组结构。jdk1.0版本。线程安全的。无论增删还是查询都非常慢.已被ArrayList替代。
特殊方法:
void add(int index,E element) 在指定索引处添加指定元素
E remove(int index) 删除指定元素,并将这个被删除的元素返回
E get(int index) 根据元素索引获取指定元素对象
E set(int index, E element)用指定元素替换列表中指定位置的元素 将被替换掉的元素对象返回
代码实现:
package cn.itcast3; import java.util.ArrayList; import java.util.List; public class Demo { public static void main(String[] args) { List list = new ArrayList(); list.add("史进"); list.add("燕顺"); list.add("杨林"); list.add("杨志"); System.out.println(list); list.add(2, "花荣"); System.out.println(list); String remove = (String)(list.remove(3)); System.out.println(remove); System.out.println(list); System.out.println("========================="); System.out.println(list.get(2)); System.out.println(list.set(2,"李广")); System.out.println(list); } }
int indexOf(Object o) 通过内容返回索引。返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1
int lastIndexOf(Object o) 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1。
代码实现:
package cn.itcast3; import java.util.ArrayList; import java.util.List; import cn.itcast2.Person; public class Demo2 { public static void main(String[] args) { List list = new ArrayList(); list.add(120); list.add(10); list.add(10); list.add(10); System.out.println(list.indexOf(10)); System.out.println(list.lastIndexOf(10)); List list2 = new ArrayList(); Person p = new Person("花荣",18); list2.add(p); list2.add(new Person("孙悟空",503)); list2.add(new Person("牛魔王",600)); list2.add(new Person("朱茵",42)); System.out.println(list2.indexOf(new Person("花荣", 18))); System.out.println(list2.indexOf(p)); } }
LinkedList: List的链表实现,提供了许多头尾操作
public void addFirst(E e) 在集合头部添加元素
public void addLast(E e) 在集合尾部添加元素
public E getFirst() 获取头部元素
public E getLast() 获取尾部元素
增强for循环(foreach循环):
用于快速遍历集合或数组的方式
格式:
for (容器内类型 临时变量 : 被遍历的容器){
使用临时的变量
}
代码实现:
package cn.itcast; import java.util.LinkedList; package cn.itcast; import java.util.LinkedList; public class Demo3 { public static void main(String[] args) { LinkedList ll = new LinkedList(); ll.add("石秀"); ll.add("时迁"); ll.add("石头"); System.out.println(ll); ll.addFirst("石破天"); ll.addLast("史进"); for (Object s: ll) { String s2 = (String)s; System.out.println(s2); } System.out.println("=========================="); System.out.println(ll.getFirst()); System.out.println(ll.getLast()); } }
Set接口:单列集合,无序,元素不得重复。
Set方法取出元素只能使用迭代器。
Set主要子类:
HashSet:线程不安全,存取速度快
底层结构为哈希表结构,即区分元素时使用hash值。可以通过hashCode与equals方法的重写,保证元素唯一性。具体代码体现为:先判断哈希值是否相等,再判断equals方法是否返回true。true则为相同元素,存储元素失败,false则为不同元素,存储元素成功。
TreeSet: 线程不安全,可以对集合中的元素进行排序。
通过Comparable让集合内元素具备比较性。
通过Comparator让集合具备比较某种类型元素的能力。
当Comparator与Comparable冲突时,以Comparator作为标准。
LinkedHashSet:在HashSet集合的基础上,使迭代顺序可预测
HashSet代码实现:
package cn.itcast2; import java.util.HashSet; import java.util.Set; public class Demo { public static void main(String[] args) { Set set = new HashSet(); String name = "梅超风"; String name2 = "杨过"; String name3 = "小龙女"; String name4 = "公孙策"; String name5 = "包拯"; String name6 = "元芳"; String name7 = "元芳"; set.add(name); set.add(name2); set.add(name3); set.add(name4); set.add(name5); set.add(name6); set.add(name7); System.out.println(set); Set set2 = new HashSet(); set2.add(new Light("白炽灯",40)); set2.add(new Light("疝气灯",200)); set2.add(new Light("霓虹灯",20)); set2.add(new Light("霓虹灯",20)); System.out.println(set2); } }
TreeSet代码实现:
package cn.itcast2; import java.util.TreeSet; public class Demo4 { public static void main(String[] args) { TreeSet ts = new TreeSet(); String name = "b黄月英"; String name2 = "a小乔"; String name3 = "d貂蝉"; String name4 = "c大乔"; String name5 = "c大乔"; ts.add(name); ts.add(name2); ts.add(name3); ts.add(name4); ts.add(name5); for(Object obj : ts) { String s= (String)obj; System.out.println(s); } TreeSet ts2 = new TreeSet(); Integer i = new Integer("10"); Integer i2 = new Integer("100"); Integer i3 = new Integer("120"); Integer i4 = new Integer("130"); ts2.add(i2); ts2.add(i4); ts2.add(i); ts2.add(i3); System.out.println(ts2); } }
LinkedHashSet代码实现:
package cn.itcast2; import java.util.Iterator; import java.util.LinkedHashSet; public class Demo3 { public static void main(String[] args) { LinkedHashSet lhs = new LinkedHashSet(); lhs.add("b许攸"); lhs.add("a曹操"); lhs.add("d贾诩"); lhs.add("c周瑜"); lhs.add("c周瑜"); Iterator iterator = lhs.iterator(); while(iterator.hasNext()) { Object next = iterator.next(); String s = (String)next; System.out.println(s); } } }
泛型
用泛型的好处:
用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数传递。
泛型的优点:
提高程序的安全性
将运行期问题转移到了编译期
省去了类型强转的麻烦
优化了程序设计
泛型的使用:
将运行时异常提前到编译期
提高了安全性
省去了类型强制转换的麻烦
泛型类:在类上定义泛型,类中使用该类型代码实现:
package cn.itcast2; import java.util.ArrayList; import java.util.Iterator; public class Demo { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); list.add("唐嫣"); list.add("柳岩"); list.add("baby"); list.add("祖蓝"); // list.add(100); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String string = iterator.next(); System.out.println(string); } for (String string : list) { System.out.println(string); } } }
格式:class 类名<T>{使用T}
代码实现:
package cn.itcast2; public class Demo4 { public static void main(String[] args) { Demo3<String> demo3 = new Demo3<String>(); demo3.setT("我是一个字符串"); String t = demo3.getT(); System.out.println(t); Demo3<Integer> demo32 = new Demo3<Integer>(); demo32.setT(123); Integer t2 = demo32.getT(); System.out.println(t2); //Demo3<int> demo33 = new Demo3<>(); // Demo3<String, Integer> demo3 = new Demo3<String, Integer>(); // // demo3.setT("String"); // String t = demo3.getT(); // // demo3.method(100); } }
泛型方法:在方法上定义泛型,方法内使用泛型,与类无关。
格式:public <T> void method(){使用T}
代码实现:
package cn.itcast2; public class Demo6<T> { public static void main(String[] args) { Demo6<String> demo6 = new Demo6<String>(); demo6.method("我是泛型类中指定的类型"); Integer i = 100; demo6.method2(i); } public void method(T t) { System.out.println(t); } public <E> void method2(E e) { E e2 = e; System.out.println(e2); } }
泛型接口:在接口上使用泛型。
格式:interface 接口名<T>{}
在类实现接口时明确泛型类型
在类实现接口时仍不明确泛型类型,在创建对象时明确泛型类型
代码实现:
package cn.itcast2; public class MyClass implements MyInterface<String> { @Override public void method(String t) { System.out.println(t); } }
package cn.itcast2; public class MyClass2<T> implements MyInterface<T> { @Override public void method(T t) { System.out.println(t); } }
package cn.itcast2; public class Demo7 { public static void main(String[] args) { MyClass mc = new MyClass(); mc.method("我是在定义类的时候,已经给接口的泛型指定了数据类型"); System.out.println("这种在定义类时已经指定了泛型的类,在创建对象时,无需再指定类型"); MyClass2<Integer> mc2 = new MyClass2<Integer>(); mc2.method(100); System.out.println("这种在定义类时没有指定泛型的类,在创建对象时,需再指定类型"); } }
Map——双列集合
定义:
Map为双列集合,存储的每个元素均为键值对,对键进行约束。可以通过键找到该建对应的值。
Map集合无法返回对应的迭代器。其内容需要调用方法进行访问。
主要格式:
Map<k,v>
key - 此映射所维护的键的类型
value - 映射值的类型
主要子类:
HashMap:底层为哈希表结构的Map集合。
Hashtable:底层为哈希表结构的Map集合。
TreeMap:对键进行排序,排序原理与TreeSet相同的Map集合。
LinkedHashMap:可预知顺序的HashMap集合
Map集合功能:
添加功能:
public V put(K key, V value)
删除功能:
public V remove(Object key)
获取功能:
public V get(Object key)
public Set<K> keySet()
public Collection<V> values()
判断功能:
public boolean containsKey(Object key)
public boolean containsValue(Object value)
获取长度:
public int size()
Map集合的遍历
方式一:
创建集合对象
创建元素对象
将元素放到集合中
返回这个Map中的所有键的Set集合
迭代键的Set集合,依次获取每一个键
根据Map中的每一个键获取Map中的每一个值
代码实现:
package cn.itcast2; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Demo6 { public static void main(String[] args) { method(); System.out.println("================="); method2(); System.out.println("================="); method3(); } //遍历所有的键与值 public static void method3() { //创建集合对象 Map<String, String> map = new HashMap<>(); //创建元素对象 //将元素放到集合中 map.put("操刀鬼", "曹正"); map.put("旱地忽律", "朱贵"); map.put("鬼脸", "杜兴"); map.put("母夜叉", "孙二娘"); //返回所有的键的集合 Set<String> keySet = map.keySet(); Iterator<String> iterator = keySet.iterator(); while(iterator.hasNext()) { //依次获取到每一个键 String key = iterator.next(); //根据map中的每一个键获取map中的每一个值 String value = map.get(key); System.out.println(key+":"+value); } } //遍历所有值 public static void method2() { Map<String, String> map = new HashMap<>(); map.put("操刀鬼", "曹正"); map.put("旱地忽律", "朱贵"); map.put("鬼脸", "杜兴"); map.put("母夜叉", "孙二娘"); //遍历所有的值 Collection<String> values = map.values(); // Iterator<String> iterator = values.iterator(); // while (iterator.hasNext()) { // String string = (String) iterator.next(); // System.out.println(string); // } for (String string : values) { System.out.println(string); } } //遍历所有键 public static void method() { Map<String, String> map = new HashMap<>(); map.put("操刀鬼", "曹正"); map.put("旱地忽律", "朱贵"); map.put("鬼脸", "杜兴"); map.put("母夜叉", "孙二娘"); //遍历所有的键 Set<String> keySet = map.keySet(); // Iterator<String> iterator = keySet.iterator(); // while(iterator.hasNext()) { // System.out.println(iterator.next()); // } for (String string : keySet) { System.out.println(string); } } }
方式二:
public Set<Map.Entry<K,V>> entrySet() 返回此映射所包含的映射关系的 Set 视图。
Entry:
代码实现:映射项,即键值对对应关系
K getKey() 获取键
V getValue() 获取值
package cn.itcast2; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import java.util.Set; public class Demo7 { public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); map.put("胡一菲", "曾小贤"); map.put("张子萱", "曾小贤"); map.put("静静", "曾小贤"); //调用entrySet方法,返回键值对对应关系的Set集合 Set<Entry<String,String>> entrySet = map.entrySet(); //迭代键值对对应关系集合 Iterator<Entry<String, String>> iterator = entrySet.iterator(); //迭代拿到每一个对应关系 while(iterator.hasNext()) { Entry<String, String> thisEntry = iterator.next(); //通过键值对对应关系获取键 String key = thisEntry.getKey(); //通过键值对对应关系获取值 String value = thisEntry.getValue(); System.out.println(key+":"+value); } } }
Map签到Map的代码实现:
package cn.itcast2; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Test2 { public static void main(String[] args) { //创建集合对象 Map学校 第一个泛型是:学校名称(String) 第二个泛型:学校的班级(Map) //班级Map:第一个泛型:班级名称(String) 第二个泛型:班级个数(Integer) //创建学校集合 Map<String, Map<String,Integer>> school = new HashMap<String, Map<String,Integer>>(); //为北京准备班级(为school这个集合准备元素对象) String name = "北京总部"; Map<String, Integer> class1 = new HashMap<String, Integer>(); //为第一个班添加内容 class1.put("javaSE", 5); class1.put("javaEE", 4); class1.put("Android", 4); class1.put("iOS", 4); //为上海准备班级(为school这个集合准备另外的元素对象) String name2 = "上海分校"; Map<String, Integer> class2 = new HashMap<String, Integer>(); //为第一个班添加内容 class2.put("javaSE", 2); class2.put("javaEE", 3); class2.put("Android", 2); class2.put("iOS", 10); school.put(name, class1); school.put(name2, class2); System.out.println(school); //遍历 //获取学校的所有元素对象 //返回所有学校名称的set集合 (key的set集合) Set<String> keySet = school.keySet(); Iterator<String> iterator = keySet.iterator(); while (iterator.hasNext()) { //依次拿到每一个学校的key String outKey = (String) iterator.next(); System.out.println(outKey); //根据学校的key找到学校对应的值 Map<String, Integer> outMap = school.get(outKey); //获取每一个学校的key的Set集合 Set<String> innerKeySet = outMap.keySet(); Iterator<String> iterator2 = innerKeySet.iterator(); while (iterator2.hasNext()) { //依次找到每一个内部Map的key String innerKey = iterator2.next(); //再根据每一个内部Map的Key找到内部Map的value Integer innerValue = outMap.get(innerKey); //打印集合内容 System.out.println("\t"+innerKey+":"+innerValue); } } } }