------- android培训、java培训、期待与您交流! ----------
----------------------------------------集合概念----------------------------------------
对象数组:Student[] stuArray = new Student[120];
1.定义了一个120个长度的Student数组;
2.数组的每个元素存储的是一个:Student对象的引用;
3.此时,没有任何的Student对象产生;
4.由于数组是引用类型的数组,所以每个元素都被初始化为:null
对象数组的弊端:
1.一旦确定长度后,其长度就不能再更改了;这对我们程序员使用起来非常的不方便;
2.数组定义时需要指定数据类型,那么就只能存储这个类型的数据;
针对数组的弊端:Java为我们程序员提供了一种新的工具(集合)
1.集合的作用:就是用来装"对象的引用";
2.这些集合就类似于"仓库",我们可以将它看做是一个:可以存储无限数量的引用的一个大仓库
我们程序员使用时,只需要往里面增、删、改、查元素,其它的操作我们不需要管。
存储Student对象,使用数组,一旦定义长度,之后就不能改变;如果我们使用"集合"存储,我们就不用关心长度的问题;
集合结构图
----------------------------------------Collection的基本方法和批量方法----------------------------------------
基本方法:
注意:如果大家在方法的形参或返回值类型中看到E字母,可以把它当做:Object
boolean add(Object e):将参数e添加到集合
boolean remove(Object o):将参数o从集合中移除
void clear():清空集合
boolean contains(Object o):基于equals()进行判断;
boolean isEmpty():判断集合是否为空
int size():集合中元素的数量;
public class Demo { public static void main(String[] args) { //1.定义集合对象 Collection col = new ArrayList();//多态:可存储重复元素 Collection col2 = new HashSet();//不能存储重复元素; //2.向仓库中添加元素 System.out.println(col.add("孙悟空")); System.out.println(col.add("猪八戒")); System.out.println(col.add("沙师弟")); System.out.println(col.add("唐僧")); System.out.println(col.add("唐僧")); System.out.println("---------------------------"); System.out.println(col2.add("孙悟空")); System.out.println(col2.add("猪八戒")); System.out.println(col2.add("孙悟空")); System.out.println("集合元素:" + col); //3.移除元素 System.out.println("删除元素:唐僧: " + col.remove("唐僧")); System.out.println("删除元素:白骨精:" + col.remove("白骨精")); System.out.println("集合元素:" + col); //4.void clear() // col.clear(); // System.out.println("清空集合后:" + col); //5.boolean contains(Object o) System.out.println("是否包含:白骨精:" + col.contains("白骨精")); System.out.println("是否包含:孙悟空:" + col.contains("孙悟空")); //6.boolean isEmpty() // col.clear(); System.out.println("集合是否为空:" + col.isEmpty()); //7.int size(): System.out.println("集合中元素的数量:" + col.size()); } }
批量操作元素的方法:
boolean addAll(Collection c):将参数集合,一次性全部添加到当前集合
boolean removeAll(Collection c):移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操
boolean containsAll(Collection c):如果此 collection 包含指定 collection 中的所有元素,则返回 true
boolean retainAll(Collection c):移除此 collection 中未包含在指定 collection 中的所有元素。
public class Demo { public static void main(String[] args) { Collection c1 = new ArrayList(); c1.add("孙悟空"); c1.add("猪八戒"); c1.add("唐三藏"); Collection c2 = new ArrayList(); c2.add("白骨精"); c2.add("蜘蛛精"); c2.add("狐狸精"); //将集合c2中的所有元素,一次性全部添加到c1中 /*c1.addAll(c2); System.out.println("c1.size : " + c1.size());//6 System.out.println("c2.size : " + c2.size());//3 System.out.println("c1 : " + c1); System.out.println("c2 : " + c2); */ //移除c1中c2的所有元素 /*c1.removeAll(c2); System.out.println("c1 : " + c1); System.out.println("c2 : " + c2);*/ //c1中是否包含c2 // System.out.println(c1.containsAll(c2)); System.out.println(c1.retainAll(c2)); System.out.println("c1 : " + c1); System.out.println("c2 : " + c2); } }
Collection类型的集合,有两种基本的遍历方法:
1.Object[] toArray()方法:
2.迭代器:Iterator iterator();
Iterator(接口):
boolean hasNext(): 如果仍有元素可以迭代,则返回 true。
Object next() :返回迭代的下一个元素。
public class Demo { public static void main(String[] args) { Collection c1 = new ArrayList(); c1.add("孙悟空"); c1.add("猪八戒"); c1.add("唐三藏"); //遍历方式一: Object[] objArray = c1.toArray(); for(int i = 0;i < objArray.length ; i++){ System.out.println(objArray[i]); } System.out.println("---------------------------"); //遍历方式二:迭代器 Iterator it = c1.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }
Collection(接口):
|--List(接口):1.可以存储重复的;2.有序的(取出时的顺序同存入时一致)
特有方法:
void add(int index,E element):将element添加到index位置;原index位置上元素依次后移;
E remove(int index):移除index位置上的元素
E get(int index):获取index位置上的元素
E set(int index,E element):将element替换原index位置上的元素;
特有遍历方式:
方式一: ListIterator listIterator():获取List的迭代器。ListIterator是Iterator的子接口;
跟Iterator的不同:
1.Iterator:单项的迭代器。只能向下遍历;
2.ListIterator:双向的迭代器,可以向上遍历;注意:在向上遍历前,一定要先向下遍历;
方式二:结合使用Collection的size()和List接口的get()方法,使用for循环进行遍历;
public class Demo { public static void main(String[] args) { //1.实例化一个集合 List list = new ArrayList(); list.add("张三"); list.add("李四"); list.add("王五"); Iterator it = list.iterator(); while(it.hasNext()){ System.out.println(it.next()); } //在"李四"之前,插入一个"赵七" list.add(1,"赵七"); System.out.println("list :" + list); //移除"赵七" list.remove(1); System.out.println("移除赵七后:" + list); //获取王五 System.out.println("获取王五:" + list.get(2)); //将王五替换为赵七 list.set(2, "赵七"); System.out.println("将王五替换为赵七后:" + list); //结合Collection的size()和List的get()方法,可以遍历List类型的集合: for(int i = 0; i < list.size() ; i++){ System.out.println(list.get(i)); } System.out.println("-----------------------"); //获取一个ListIterator ListIterator listIt = list.listIterator(); System.out.println("先向下遍历:"); while(listIt.hasNext()){ System.out.println(listIt.next()); } System.out.println("向上遍历:"); while(listIt.hasPrevious()){ System.out.println(listIt.previous()); } System.out.println("====================="); } }
并发修改异常:
1.Iterator:remove()方法不会触发并发修改异常;
2.ListIterator:
remove()方法不会触发并发修改异常;
set()方法不会触发并发修改异常;
add()方法不会触发并发修改异常;
3.当使用迭代器遍历元素时,通过List的对象去修改元素内容时,
会引发并发修改异常:ConcurrentModificationException
解决:使用迭代器遍历,如果要修改集合,就要通过迭代器去修改。不要通过List对象修改;
----------------------------------------各数据结构特点----------------------------------------
1.栈:先进后出
2.队列:先进先出
3.数组:随机获取元素快,增、删慢;
4.链表:查询慢,增、删非常快;
----------------------------------------List接口的三个子类----------------------------------------
Collection(接口)
|--List(接口):1.有序的;2.可以存储重复值
|--ArrayList(类):1.数组实现;2.不是同步的(不保证线程安全),效率高;
|--Vector(类):1.数组实现;2.同步的(线程安全的),效率低
特有方法:
public void addElement(E obj):添加一个元素;(相当于Collection的add()方法)
public E elementAt(int index):获取index位置上的元素;(相当于List的get()方法)
|--LinkedList(类):1.链表实现。2.非同步的(线程不安全的),效率高;
特有方法:
public void addFirst(E e)及addLast(E e):
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()
|--Set(接口):1.无序的;2.不能存储重复值
public class Demo { public static void main(String[] args) { // 1.实例化一个Vector Vector vec = new Vector(); System.out.println(vec.capacity()); // 2.填充集合 vec.add(new Student("刘德华", 20)); vec.add(new Student("张学友", 22)); vec.addElement(new Student("章子怡", 18)); vec.addElement(new Student("汪峰", 80)); // 3.遍历 for (int i = 0; i < vec.size(); i++) { Student stu = (Student) vec.elementAt(i); System.out.println(stu.name + "," + stu.age); } } } //学生类 public class Student { String name; int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } }
public class Demo { public static void main(String[] args) { LinkedList list = new LinkedList(); /*list.add("aaa"); list.add("bbb"); list.add("ccc");*/ list.addFirst("aaa"); list.addFirst("bbb"); list.addFirst("ccc"); for(int i = 0;i < list.size() ; i++){ // System.out.println(list.get(i)); System.out.println(list.getLast()); list.removeLast(); i--; } } }
Arrays类的_asList方法_将数组转换为集合:
public class Demo { public static void main(String[] args) { List<String> strList = Arrays.asList("张三", "李四", "王五", "周六"); List<Integer> intList = Arrays.asList(10, 2, 34, 2, 5, 4, 34, 2); int[] arr = { 1, 2, 3, 4, 5 }; List<int[]>array = Arrays.asList(arr);//0x2233 for (int[] o : array) { for (int i = 0; i < o.length; i++) { System.out.println(o[i]); } } }
集合嵌套之ArrayList嵌套ArrayList
一个班的学员:刘德华, 张学友, 郭富城,黎明;另一个班的学员:章子怡, 范冰冰, 李宇春, 罗玉凤
将上述两个集合添加到一个大集合中;
public class Demo { public static void main(String[] args) { List<String> class1List = new ArrayList<>(); class1List.add("刘德华"); class1List.add("张学友"); class1List.add("郭富城"); class1List.add("黎明"); List<String> class2List = new ArrayList<>(); class2List.add("章子怡"); class2List.add("范冰冰"); class2List.add("李宇春"); class2List.add("罗玉凤"); List<List<String>> list = new ArrayList<>(); list.add(class1List); list.add(class2List); for (List<String> classList : list) { for (String s : classList) { System.out.println(s); } } } }
Collection(接口)
|--Set(接口):1.无序的;2.不能存储重复值
|--HashSet(类):哈希表结构;综合了数组和链表的优点了。查询快;增、删快;
1.重复性验证:第一步:哈希值;第二步:equals():
使用HashSet存储自定义对象
1.需要判断出两个对象中的属性值是否完全一样,需要重写hashCode()和equals();
2.怎么重写? 鼠标-->右键-->source-->Generate hashCode() and equals()
|--LinkedHashSet(类):链表和哈希表结构:
1.有序的;(由链表保证顺序)
2.不存储重复值;(由哈希表保证唯一):hashCode-->equals()
|--TreeSet(类):树结构;特点:对元素进行排序;
1.树结构存储;验证唯一性:如果"比较器"的"比较的方法"返回0,则认为是相同对象;
2.树结构的特点:对元素进行排序:
1).自然排序:
1.存储的对象,必须实现:Comparable接口
2.重写compareTo()方法;
2).比较器排序:
1.存储的对象无需实现任何接口;
2.需要自定义一个比较器,实现:Comparator接口,重写compare()方法;
3.构造TreeSet时,为其传递一个"比较器对象"给构造方法;
说明:第2,3步,我们一般使用"匿名内部类"实现;
使用HashSet(哈希表结构)存储自定义对象
1.需要判断出两个对象中的属性值是否完全一样,需要重写hashCode()和equals();
public class Student { String name; int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
public class Demo { public static void main(String[] args) { Set<Student> stuSet = new HashSet<>(); stuSet.add(new Student("张三", 20)); stuSet.add(new Student("李四", 22)); stuSet.add(new Student("王五", 24)); stuSet.add(new Student("王五", 24));//存不进去,set不存重复值 for (Student stu : stuSet) { System.out.println(stu.name + "---" + stu.age); } } }
LinkedHashSet:链表和哈希表结构:
1.有序的;(由链表保证顺序)
2.不存储重复值;(由哈希表保证唯一):hashCode-->equals()
public class Demo { public static void main(String[] args) { LinkedHashSet<String> set = new LinkedHashSet<>(); // 添加元素 set.add("aaa"); set.add("bbb"); set.add("ccc"); set.add("ddd"); set.add("ddd");// 不存储重复值;(由哈希表保证唯一) // 遍历集合 for (String s : set) { System.out.println(s); } } }
TreeSet:树结构:特点:对元素进行排序;排序的方式:
一:自然排序;
二:比较器排序;
public class Demo { public static void main(String[] args) { TreeSet<Integer> tree1 = new TreeSet<>(); // 存无序 tree1.add(20); tree1.add(18); tree1.add(23); tree1.add(22); tree1.add(17); tree1.add(24); tree1.add(19); tree1.add(18); tree1.add(24); // 取有序 for (Integer i : tree1) { System.out.print(i+","); } }
TreeSet类_比较器排序:
public class Student{ String name; int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } }
public class Demo { public static void main(String[] args) { TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { // 1.先比较年龄 int n1 = o1.age - o2.age; // 2.再判断姓名 int n2 = (n1 == 0 ? o1.name.compareTo(o2.name) : n1); return n2; } }); set.add(new Student("张三", 20)); set.add(new Student("李四", 19)); set.add(new Student("赵七", 28)); set.add(new Student("赵七", 28));// 重复的元素; for (Student stu : set) { System.out.println(stu.name + "--" + stu.age); } } }
--------------------------------Map接口------------------------------------
Map(接口):双列集合:键、值对存储 注意:Map的数据结构都是引用在"键"上
|--HashMap:哈希表
|--LinkedHashMap:哈希表和链表结构;有序的双列集合
|--TreeMap:树结构
TreeMap需要对"键"进行排序,排序的方式:
1.自然排序:
1).作为"键"的对象,一定要实现:Comparable接口
2).重写compreTo()方法;
2.比较器排序:
1).自定义比较器对象,要实现:Comparator接口;
2).重写compare()方法;
3).在实例化TreeMap时,将自定义的比较器对象传入TreeMap的构造方法;
Map集合的基本功能:
1.put(K key ,V value):添加元素;
2.clear():清空集合
3.remove(Object key):移除键key
4.containsKey(Object key):判断键key在集合中是否存在;
5.boolean containsValue(Object value):判断值value,在集合中是否存在;
5.isEmpty():判断集合是否为空;
注意:关于put()方法的返回值:
1.如果put()进去一个未曾添加的一个新键值对,那么返回null;
2.如果put()进去一个已经存在的键,那么用"新值"替换"原值";
Map集合的获取功能测试
V get(Object key):用一个key查找对应的值;
Set<K> keySet():返回所有键的Set集合;
Collection<V> values():获取所有value的集合;
Set<Map.Entry<K,V>> entrySet():获取所有"键值对对象";
Map的遍历方式只有两种:
1.keySet:先获取所有键的集合,然后遍历键的集合,根据每个键去获取值;
2.entrySet:获取所有的"键值对对象"的集合,然后遍历;
public class Demo { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); System.out.println(map.put("it001", "刘德华")); System.out.println(map.put("it002", "张学友")); System.out.println(map.put("it003", "章子怡")); System.out.println(map.put("it004", "撒贝宁")); System.out.println(map.put("it004", "汪峰")); // 清空集合 // map.clear(); // 移除it004 // System.out.println("移除it005结果:" + map.remove("it005")); // System.out.println("移除it004结果:" + map.remove("it004")); // 判断键it004是否存在 System.out.println("判断键it004是否存在:" + map.containsKey("it004")); System.out.println("判断键it005是否存在:" + map.containsKey("it005")); System.out.println("判断章子怡是否存在:" + map.containsValue("章子怡")); System.out.println("判断汪峰是否存在:" + map.containsValue("汪峰")); System.out.println("集合是否为空: " + map.isEmpty()); System.out.println(map); } }
public class Demo { public static void main(String[] args) { Map<String, String> map = new HashMap<>(); map.put("it001", "刘德华"); map.put("it002", "张学友"); map.put("it003", "章子怡"); map.put("it004", "撒贝宁"); // System.out.println("获取it004对应的值:" + map.get("it004")); // 遍历Map集合的一种方式: Set<String> keys = map.keySet(); for (String key : keys) { System.out.println(key + "----" + map.get(key)); } System.out.println("------------Map.Entry遍历--------------"); // 遍历Map集合的第二种方式: Set<Map.Entry<String, String>> entrySet = map.entrySet(); for (Map.Entry<String, String> en : entrySet) { System.out.println(en.getKey() + "---" + en.getValue()); } } }
LinkedHashMap的概述和使用:
public class Demo { public static void main(String[] args) { LinkedHashMap<String, String> map = new LinkedHashMap<>(); map.put("it001", "刘德华"); map.put("it002", "张学友"); map.put("it003", "黎明"); map.put("it004", "郭富城"); // 遍历 // 1.keySet(): // 2.entrySet(): Set<String> keySet = map.keySet(); for (String key : keySet) { System.out.println(key + "--" + map.get(key)); } }
TreeMap_键是Student值是String的案例:
public class Student { String name; int age; public Student(String name, int age) { super(); this.name = name; this.age = age; } }
public class Demo { public static void main(String[] args) { TreeMap<Student, String> map = new TreeMap<>(new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { // 1.先按年龄排 int n1 = o1.age - o2.age; // 2.如果年龄相同,按姓名排 int n2 = (n1 == 0 ? o1.name.compareTo(o2.name) : n1); return n2; } }); map.put(new Student("张三", 20), "it001"); map.put(new Student("李四", 18), "it003"); map.put(new Student("王五", 22), "it002"); map.put(new Student("周六", 17), "it004"); Set<Student> keySet = map.keySet(); for (Student stu : keySet) { System.out.println(stu.name + "," + stu.age + "---" + map.get(stu)); } } }
java.util.Collections(工具类):对集合操作的工具类;
public static <T> void sort(List<T> list):根据元素的自然顺序 对指定列表按升序进行排序。-->compareTo()
public static <T> int binarySearch(List<?> list,T key):在集合list中查找key:要先排序;
public static <T> T max(Collection<?> coll):获取集合中的最大元素;
public static void reverse(List<?> list):反转集合内的所有元素;
public static void shuffle(List<?> list):打乱集合中所有元素的顺序;
public class Demo { public static void main(String[] args) { List<String> arrayList = new ArrayList<>(); arrayList.add("ccc"); arrayList.add("bbb"); arrayList.add("aaa"); arrayList.add("ddd"); System.out.println(arrayList); // 排序 Collections.sort(arrayList); System.out.println(arrayList); // 查找元素"ddd" System.out.println("查找元素ddd: " + Collections.binarySearch(arrayList, "ddd")); System.out.println("集合中的最大元素:" + Collections.max(arrayList)); Collections.reverse(arrayList); System.out.println("反转集合内的元素:" + arrayList); Collections.shuffle(arrayList); System.out.println("打乱集合内的元素的顺序:" + arrayList); } }