集合Collect
package com.collection; import org.junit.Test; import java.util.*; /** * *一、集合框架的概述 * 1.集合、数组都是对多个数据进行存储操作的结构,简称Java容器。 * 说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg;.avi,数据库中, * * * 2.1数组在存储多个数据方面的特点: * >一旦初始化以后,其长度就确定了。 * >数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了 * 比如: String[] arr ; int[] arr1; Object[] arr2; * 2.2数组在存储多个数据方面的缺点: * >一旦初始化以后,其长度就不可修改。 * >数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常不便。同时效率不高。 * >获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用。 * >数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足。 * *Java集合可分为Collection和 Map 两种体系: * >collection接口:单列数据,定义了存取一组对象的方法的集合 * √List:元素有序、可重复的集合 * √set:元素无序、不可重复的集合 * >Map接口:双列数据,保存具有映射关系“key-value对”的集合 * *二、集合框架 * |----collection接口 :单列集合,用来存储一个一个的对象 * /----List接口: 存储有序的、可重复的数据 * /----ArrayList、LinkedLis、Vector * /-----Set接口: 存储无序的、不可重复的数据 -->高中讲的“集合” * /----HashSet、linkedHashSet、TreeSet * |----Map接口:双列集合,用来存储一对(key - value)一对的数据 -->高中的函数:y=f(x) * /----HashMap、LikedHashMap、TreeMap、HashTable、Properties * * @author Dixon * @create 2022-06-05 21:06 */ public class CollectionTest { //Collection接口中声明的方法的测试 /** * 结论: * 向Collection接口的实现类的对象中添加数据obj时,要求obj所在类要重写equals(). */ @Test public void Test1(){ Collection coll = new ArrayList(); //1.add(Object e):将元素e添加到集合coLL中 coll.add("AA"); coll.add("BB"); coll.add("123"); //自动装箱 coll.add(new Date()); //2.size:获取添加的元素的个数 System.out.println(coll.size()); //4 //3.addAll(Collection coll):将coLl集合中的元素添加到当前的集合中 Collection coll1 = new ArrayList(); coll1.add("456"); coll1.add("CC"); coll1.addAll(coll); System.out.println(coll1.size()); //6 System.out.println(coll1); //4.clear():清空集合元素 coll.clear(); //5.isEmpty():判断当前集合是否为空 System.out.println(coll.isEmpty());//false,清空后成true //6.contains(Object obj):判断当前集合是否包含obj ///我们在判断时会调用obj对象所在类的equals(). Collection coll2 = new ArrayList(); coll2.add(123); coll2.add(456); coll2.add(new String("TOM")); coll2.add(false); coll2.add(456); coll2.add(new Person("Jerry",20)); System.out.println(coll2.contains(123));//true System.out.println(coll2.contains(new String("TOM")));//true System.out.println(coll2.contains(new Person("Jerry",20)));//false //7.containsAll(contains coll1):判断形参coll中的所有元素是否都存在当前集合中。 Collection coll3 = Arrays.asList(123, 456); System.out.println(coll2.containsAll(coll3));// true 只要有一个不在就是false //8.remove(Object obj): Collection coll4 = new ArrayList(); coll4.add(123); coll4.add(456); coll4.add(new Person("Jerry",20)); coll4.add(new String("TOM")); coll4.add(false); coll4.remove(123); System.out.println(coll4); System.out.println(coll4.remove(new Person("Jerry",20))); System.out.println(coll4); //8.removeAll(contains coll1):差集:从当前集合中移除coll1中所有的元素 Collection coll5 = Arrays.asList(123, 456); coll4.removeAll(coll5); System.out.println(coll4); //9.retainALl(Collection coll1):交集:获取当前集合和coll1集合的交集,并返回给当前集合 // Collection coll6 = Arrays.asList(123, 456,789,22); coll4.add(123); coll4.add(456); System.out.println(coll4); Collection coll7 = Arrays.asList(123, 456,7,8899,44); coll4.retainAll(coll7); System.out.println(coll4); //10.equals(Object obj): 要想返回true,需要当前集合和形参集合的元素都相同。 Collection coll8 = new ArrayList(); coll8.add(123); coll8.add(456); coll8.add(new Person("Jerry",20)); coll8.add(new String("TOM")); coll8.add(false); Collection coll9 = new ArrayList(); coll9.add(123); coll9.add(456); coll9.add(new Person("Jerry",20)); coll9.add(new String("TOM")); coll9.add(false); Collection coll10 = new ArrayList(); coll10.add(456); coll10.add(123); coll10.add(false); coll10.add(new Person("Jerry",20)); coll10.add(new String("TOM")); System.out.println(coll8.equals(coll9)); //true System.out.println(coll8.equals(coll10)); //false 有序的 顺序不一样就错误 //11.hashCode():返回当前对象的哈希值 Collection coll11 = new ArrayList(); coll11.add(456); coll11.add(123); coll11.add(false); coll11.add(new Person("Jerry",20)); coll11.add(new String("TOM")); System.out.println("---------/12.集合---》数组: toArray()-----------"); //12.集合---》数组: toArray() Object[] objects = coll11.toArray(); for (int i = 0; i < objects.length; i++) { System.out.println(objects[i]); } System.out.println("---------13.数组---》集合-----------"); //13.数组---》集合 List<String> strings = Arrays.asList(new String[]{"AA", "bb", "CC"}); System.out.println(strings); //[AA, bb, CC] //注意: List<int[]> ints = Arrays.asList(new int[]{123, 111}); System.out.println(ints); //[[I@2b05039f] 返回的是一个对象 //iterator():返回iterator接口的实例,用于遍历集合元素,放到IteratorTest.java文件中 } } class Person{ private String name; private int age; public Person() { } public Person(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 boolean equals(Object o) { // System.out.println("equals方式"); if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; if (age != person.age) return false; return name.equals(person.name); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
迭代器Iterator接口
package com.collection; import org.junit.Test; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /** * * 集合元素的遍历,使用Iterator接口 * * 集合元素的遍历操作,使用迭代器Iterator接口 * 1.内部的方法: hasNext()和next() * 2.集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。 * 3.内部定义了remove(),可以在遍历的时候,删除集合中的元素。此方法不同于集合直接调用remove() * * @author Dixon * @create 2022-06-07 10:24 */ public class IteratorTest { @Test public void Test1() { Collection coll = new ArrayList(); coll.add(456); coll.add(123); coll.add(new Person("Jerry", 20)); coll.add(new String("TOM")); coll.add(false); //方式一: 不可能用的在开发中 // System.out.println(iterator.next()); // System.out.println(iterator.next()); // System.out.println(iterator.next()); // System.out.println(iterator.next()); // System.out.println(iterator.next()); // System.out.println(iterator.next()); //超出长度抛异常NoSuchElementException //方式二:不推荐 // for (int i = 0; i < coll.size(); i++) { // System.out.println(iterator.next()); // } //方式三:推荐 for (Object o : coll) { System.out.println(o); } } @Test public void Test2() { Collection coll = new ArrayList(); coll.add(456); coll.add(123); coll.add(new Person("Jerry", 20)); coll.add(new String("TOM")); coll.add(false); // Iterator iterator = coll.iterator(); //错误的方式一: 会跳着输出 结果是:123 TOM // while (iterator.next() !=null){ // System.out.println(iterator.next()); // } //错误的方式二:集合对象每次调用iterator()方法都得到一个全新的迭代器对象, // 默认游标都在集合的第一个元素之上。 while (coll.iterator().hasNext()){ System.out.println(coll.iterator().next()); } } @Test public void Test3() { Collection coll = new ArrayList(); coll.add(456); coll.add(123); coll.add(new Person("Jerry", 20)); coll.add(new String("TOM")); coll.add(false); //删除集合中TOM的数据 Iterator iterator = coll.iterator(); while (iterator.hasNext()){ Object Object = iterator.next(); if("TOM".equals(Object)){ iterator.remove(); } } // coll.remove(false); //遍历集合 iterator = coll.iterator(); // 因为上面遍历了一次,指针在最后了 while(iterator.hasNext()){ System.out.println(iterator.next()); } } }
foreach循环
package com.collection; import org.junit.Test; import java.util.ArrayList; import java.util.Collection; /** * * jdk 5.日新增了foreach循环,用于遍历集合、数组 * * * @author Dixon * @create 2022-06-07 15:11 */ public class ForEachTest { @Test public void Test1() { Collection coll = new ArrayList(); coll.add(456); coll.add(123); coll.add(new Person("Jerry", 20)); coll.add(new String("TOM")); coll.add(false); //for(集合中元素的类型 局部变量 : 集合对象) for(Object obj:coll){ System.out.println(obj); } } @Test public void Test2() { int[] arr =new int[]{1,2,3,4,5,6}; //for(数组中元素的类型 局部变量 : 数组对象) for (int i :arr) { System.out.println(i); } } @Test public void Test3() { String[] arr = new String[]{"MM","MM","MM"}; //方式一: 普通for循环赋值 // for (int i = 0; i < arr.length; i++) { // arr[i]="GG"; // } // for (int i = 0; i < arr.length; i++) { // System.out.println(arr[i]); // }//GG GG GG //方式二:增强for循环 for(String str: arr){ str="GG"; // str是新变量 } for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]); } // "MM","MM","MM" } }
ListTest
package com.collection; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; /** * * |----collection接口 :单列集合,用来存储一个一个的对象 * * /----List接口: 存储有序的、可重复的数据 * * /----ArrayList:作为List接口的主要实现类,作为List接口的主要实现类;线程不安全的,效率高; 底层使用Object[] elementData存储 * /----LinkedLis:对于频繁的插入、删除操作,使用此类效率比ArrayList高,底层使用双向链表存储 * /----Vector :作为List接口的古老实现类,线程安全的,效率低;底层使用Object[] elementData存储 * * 面试题:ArrayList、 LinkedList. Vector三者的异同? * 同:三个类都实现了List接口,存储数据的特点相同: 存储有序的、可重复的数据; * 不同点: 见上面 * * * 2. ArrayList的源码分析: * 2.1jdk 7情况下 * ArrayList list = new ArrayList();//底层创建了长度是10的object[]数组elementData * list.add(123); elementData[e] = new Integer(123); * list.add(11); * ... * 如果此次的添加导致底层elementData数组容量不够,则扩容。 * 默认情况下,扩容为原来的容量的1.5倍,同时需要将原有数组中的数据复制到新的数组中。 * * 2.2jdk 8中ArrayList的变化: * ArrayList list = new ArrayList();//底层object[] elementData初始化为{}. * 并没有创建长度为10的数组。 * list.add(123);//第一次调用add()时,底层才创建了长度10的数组,并将数据123添加到elementData * 后续的添加和扩容操作与jdk 7无异。 * * 2.3小结:jdk7中的ArrayList的对象的创建类似于单例中的饿汉式,jdk8中的ArrayList的对象的 * 创建类似于单例中懒汉式,延迟了数组的创建,节省了内存。 * * 结论:建议开发中使用带参的构造器:ArrayList list = new ArrayList(initialCapacity) * 3. LinkedList的源码分析: * LinkedList list = new linkedList();内部声明了Node类型的first和Last属性,默认值为null * list.add(123);//将123封装到Node中,创建了Node对象。 * * 其中,Node定义为:体现了LinkedList的双向链表的说法 * private static class Node<E>{ * E item; * Node<E> next;Node<E> prev; * Node(Node<E> prev, E element, Node<E> next) { * this.item = element; * this.next = next; * this.prev = prev; * } * } * 4. Vector的源码分析: jdk7和jdk8中通过Vector()构造器创建对象时,底层都创建了长度为10的数组。 * 扩容为原来的2倍。 * * * 总结:常用方法 * 增: add(object obj) * 刷: remove(int index) / remove(object obj)改: set(int index,object ele) * 查: get(int index) * 插: add(int index, object eLe)长度: size( ) * 遍历: * Iterator迭代器方式 * 增强for循环 * 普通的循环 * * * * @author Dixon * @create 2022-06-07 16:19 */ public class ListTest { @Test public void Test1(){ ArrayList list = new ArrayList(); list.add(123); list.add(456); list.add("AA"); list.add(new Person("Tom",12)); list.add(456); System.out.println(list); //1. void add(int index,object ele):在index位置插入ele元素 list.add(1,"BB"); System.out.println(list); //2.boolean addAll(int index,collection eLes): 从index位置开始将list中的所有元素添加 List list1 = Arrays.asList(1, 2, 3); list.addAll(1,list1); System.out.println(list);// 9个元素 [123, 1, 2, 3, BB, 456, AA, Person{name='Tom', age=12}, 456] //3. Object get(int index):获取指定index位置的元素 System.out.println(list.get(1)); //1 //4.indexOf(object obj):返回obj在集合中首次出现的位置 int index = list.indexOf(456); System.out.println(index); //5 如果没有返回-1 //5.int lastIndex0f(object obj):返回obj在当前集合中末次出现的位置 int lastIndex = list.lastIndexOf(456); System.out.println(lastIndex); //8 //6.object remove(int index):移除指定index位置的元素,并返回此元素 System.out.println(list); Object remove = list.remove(1); System.out.println(remove); System.out.println(list); //7.object set(int index,object ele):设置指定index位置的元素为eLe Object set = list.set(1, 999); System.out.println(set); System.out.println(list); //8.list subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合,左闭右开 List list2 = list.subList(3, 6); System.out.println(list2);// [BB, 456, AA] System.out.println("-------方式一:迭代器iterator-----------"); //方式一:迭代器iterator Iterator iterator = list.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } System.out.println("-------方式二:foreach-------------------"); //方式二:foreach for (Object o : list) { System.out.println(o); } //方式三:普通for循环 System.out.println("----------方式三:普通for循环-----------"); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } } //面试题 @Test public void testListRemove(){ ArrayList list = new ArrayList(); list.add(1); list.add(2); list.add(3); updateList(list); System.out.println(list); //1 2 } private static void updateList(List list){ list.remove(2); //remove的索引 // list.remove("2"); // remove object } }
SetTest
package com.collection; import org.junit.Test; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; /** * * Set接口的框架: * /----collection接口:单列集合,用来存储一个一个的对象 * /----Set接口:存储无序的、不可重复的数据-->高中讲的"集合” * /-----Hashset:作为Set接口的主要实现类;线程不安全,可以存储null值 * /-----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历 * 对于频繁的遍历操作,LinkedHashSet效率高于Hashset * /-----TreeSet:可以按照添加对象的指定属性,进行排序。 * * * 1. Set接口中没有额外定义新的方法,使用的都是collection中声明过的方法。 * 2.要求:向Set中添加的数据,其所在的类一定要重写hashcode()和equals() * 要求:重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码 * * 重写两个方法的小技巧:对象中用作equals()方法比较的 Field,都应该用来计算hashCode * * * * @author Dixon * @create 2022-06-08 17:02 */ public class SetTest { /** *一、Set接口:存储无序的、不可重复的数据 * 1. 无序性: 不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定 * * 2.不可重复性:保证添加的元素按照equals()判断时,不能返回true.即:相同的元素只能添加一个. * *二、添加元素的过程: 以HashSet为例: * 我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值, * 此哈希值接着通过某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断 * 数组此位置上是否已经有元素: * 如果此位置上没有其他元素,则元素a添加成功。--->情况1 * 如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值 * 如果hash值不相同,则元素a添加成功。--->情况2 * 如果hash值相同,进而需要调用元素a所在类的equals()方法: * equals()返回true,元紊α添加失败 * equals()返回faLse,则元素α添加成功。--->情况3 * 对于添加成功的情况2和情况3而言:元素a与已经存在指定索引位置上数据以链表的方式存储。 * jdk 7:元素a放到数组中,指向原来的元素。 * jdk 8:原来的元素在数组中,指向元素a * 总结: 七上八下 * * * HashSet底层:数组+链表结构 * * * * * */ //HashSet @Test public void Test1(){ HashSet set = new HashSet(); set.add(345); set.add(123); set.add(123); set.add("AA"); set.add("CC"); set.add(new Person("Tom",12)); set.add(129); Iterator iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next());// 没有按照添加顺序输出 } } //LinkedHashSet的使用 /** * * LinkedHashSet作为HashSet的子类,在添加数据的同时,每个数据还维护了两个引用,记录此数据前一个数据和后一个数据 * * //优点:对于频繁的遍历操作,LinkedHashSet效率高于Hashset * */ @Test public void Test2(){ HashSet set = new LinkedHashSet(); set.add(345); set.add(123); set.add(123); set.add("AA"); set.add("CC"); set.add(new Person("Tom",12)); set.add(129); Iterator iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); // 按照添加顺序输出 } } }
TreeSetTest
package com.collection; import org.junit.Test; import java.util.*; /** * @author Dixon * @create 2022-06-10 14:08 */ public class TreeSetTest { /** * 1./向TreeSet中添加的数据,要求是相同类的对象。 * 2.两种排序方式:自然排序(Comparable)和定制排序(Comparator) * 3.自然排序中,比较两个对象是否相同的标准为: compareTo()返回e.不再是equals(). */ @Test public void test1() { TreeSet set = new TreeSet(); //失败:不能添加不同类的对象 // set.add(123); // set.add(456); // set.add("AA"); //ClassCastException // set.add(new Person("Tom",12)); // // 举例一: // set.add(34); // set.add(12); // set.add(-43); // set.add(34); // 举例二: // set.add("哈哈"); // set.add("嘿嘿"); // set.add("哈哈哈"); // set.add("111122"); //举例三:没有重写报错ClassCastException, 2种排序 自然和定制排序 set.add(new Person("Tom", 12)); set.add(new Person("Jerry", 11)); set.add(new Person("Tim", 10)); //关注点 如果排序条件相同,所以遍历只出现一个,重写多下比较方法 set.add(new Person("SHE", 9)); set.add(new Person("SHE", 12)); //举例一从小到排序,举例二String的comparable方法排序,举例三报错ClassCastException Iterator iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } @Test public void test2() { Comparator comparator = new Comparator() { //按照年龄从小到大排序 @Override public int compare(Object o1, Object o2) { if (o1 instanceof Person && o2 instanceof Person) { Person p1 = (Person) o1; Person p2 = (Person) o2; // return Integer.compare(p1.getAge(),p2.getAge()); int compare = Integer.compare(p1.getAge(), p2.getAge()); if (compare != 0) { return compare; } else { return p1.getName().compareTo(p2.getName()); } } else { throw new RuntimeException("输入的类型不一致"); } } }; TreeSet set = new TreeSet(comparator); set.add(new Person("Tom", 12)); set.add(new Person("Jerry", 11)); set.add(new Person("Tim", 10)); set.add(new Person("Jack", 33)); set.add(new Person("DIXON", 33)); Iterator iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } public static void main(String[] args) { MyDate myDate1 = new MyDate(1993, 3, 1); MyDate myDate2 =new MyDate(1993,8,7); MyDate myDate3 =new MyDate(1993,5,21); MyDate myDate4 =new MyDate(1996,2,13); MyDate myDate5 =new MyDate(1998,11,1); Employee employee1 = new Employee("wjl", 28, myDate1); Employee employee2 = new Employee("ggg", 28, myDate2); Employee employee3 = new Employee("lll", 28, myDate3); Employee employee4 = new Employee("zzz", 25, myDate4); Employee employee5 = new Employee("w", 24, myDate5); TreeSet treeSet = new TreeSet(); treeSet.add(employee1); treeSet.add(employee2); treeSet.add(employee3); treeSet.add(employee4); treeSet.add(employee5); System.out.println("1.按照姓名来排序:"); //1).使 Employee实现 Comparable接口,并按 name 排序 Iterator iterator = treeSet.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } System.out.println("\n2.按照年龄来排序,再按姓名来排序:"); //2).创建TreeSet时传入Comparator对象,按生日日期的先后排序。 TreeSet treeSet1 = new TreeSet(new Comparator() { @Override public int compare(Object o1, Object o2) { if (o1 instanceof Employee && o2 instanceof Employee){ Employee employee1 = (Employee)o1; Employee employee2 = (Employee)o2; // return Integer.compare(employee1.getAge(),employee2.getAge()); int compare = Integer.compare(employee1.getAge(), employee2.getAge()); if (compare ==0){ return employee1.getName().compareTo(employee2.getName()); }else { return compare; } }throw new RuntimeException("类型不一致"); } }); treeSet1.add(employee1); treeSet1.add(employee2); treeSet1.add(employee3); treeSet1.add(employee4); treeSet1.add(employee5); Iterator iterator1 = treeSet1.iterator(); while (iterator1.hasNext()){ System.out.println(iterator1.next()); } } } /** *练习题: * 1.定义一个Employee类: * 该类包含: private成员变量name,age,birthday,其中 birthday 为MyDate 类的对象;· * 并为每一个属性定义 getter, setter方法;。并重写 toString方法输出name, age, birthday * MyDate类包含: * private成员变量year,month,day;并为每一个属性定义 getter,setter方法; * 创建该类的5个对象,并把这些对象放入TreeSet集合中(下一章:TreeSet需使用泛型来定义)v * 分别按以下两种方式对集合中的元素进行排序,并遍历输出:, * 1).使 Employee实现 Comparable接口,并按 name 排序 * 2).创建TreeSet时传入Comparator对象,按生日日期的先后排序。 * * */ class Employee implements Comparable{ private String name; private int age; private MyDate birthday; public Employee() { } public Employee(String name, int age, MyDate birthday) { this.name = name; this.age = age; this.birthday = birthday; } 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; } public MyDate getBirthday() { return birthday; } public void setBirthday(MyDate birthday) { this.birthday = birthday; } @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", age=" + age + ", birthday: " + birthday + '}'; } @Override public int compareTo(Object o) { if (o instanceof Employee){ Employee employee =(Employee)o; return this.name.compareTo(employee.getName()); } throw new RuntimeException("输入参数类型不一致"); } } class MyDate{ private int year; private int month; private int day; public MyDate() { } public MyDate(int year, int month, int day) { this.year = year; this.month = month; this.day = day; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; } public int getDay() { return day; } public void setDay(int day) { this.day = day; } @Override public String toString() { return "year=" + year + ", month=" + month + ", day=" + day; } }
package com.collection; import org.junit.Test; import java.util.ArrayList; import java.util.HashSet; import java.util.List; /** * @author Dixon * @create 2022-06-15 17:41 */ public class ThreeTest2 { /** * 面试题1: * 练习:在List内去除重复数字值,要求尽量简单 */ public static List duplicateList(List list){ HashSet hashSet = new HashSet(); hashSet.addAll(list); return new ArrayList(hashSet); } //如果是自己的类 需要重写equals()和 hashCode() @Test public void test1() { List list = new ArrayList(); list.add(new Integer(1)); list.add(new Integer(2)); list.add(new Integer(2)); list.add(new Integer(4)); list.add(new Integer(4)); list.add(new Integer(1)); list.add(new Integer(5)); List list2 = duplicateList(list); for (Object o :list2 ) { System.out.println(o); } } /** * 面试题2: */ @Test public void test2() { HashSet set = new HashSet(); Person1 p1 = new Person1(1001,"AA"); Person1 p2 = new Person1(1002,"BB"); set.add(p1); set.add(p2); System.out.println(set); //[Person{id=1002, name='BB'}, Person{id=1001, name='AA'}] p1.setName("CC"); set.remove(p1); System.out.println(set); //[Person{id=1002, name='BB'}, Person{id=1001, name='CC'}] set.add(new Person1(1001,"CC")); System.out.println(set);//[Person{id=1002, name='BB'}, Person{id=1001, name='CC'}, Person{id=1001, name='CC'}] set.add(new Person1(1001,"AA"));//[Person{id=1002, name='BB'}, Person{id=1001, name='CC'}, Person{id=1001, name='CC'}, Person{id=1001, name='AA'}] System.out.println(set); } } class Person1{ private int id; private String name; public Person1() { } public Person1(int id, String name) { this.id = id; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person1 person1 = (Person1) o; if (id != person1.id) return false; return name != null ? name.equals(person1.name) : person1.name == null; } @Override public int hashCode() { int result = id; result = 31 * result + (name != null ? name.hashCode() : 0); return result; } @Override public String toString() { return "Person{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
1.集合Collection中存储的如果是自定义类的对象,需要自定义类重写哪个方法?为什么?
equals()方法。contains()/remove()/retainsAll() .....
List: equals()方法
Set:(HashSet、LinkedHashSet为例):equals()、hashCode()
(TreeSet为例):Comparable: compareTo(Object obj)-
Comparator: compare(Object o1,Object o2)
2. ArrayList,LinkedList,Vector三者的相同点与不同点?【面试题】
Map
package com.collection.Map; import org.junit.Test; import java.util.*; /** *一、Map的实现类的结构 * |----Map:双列数据,存储key-value对的数据---类似于高中的函数: y = f(x) * |-----HashMap: 作为Map的主要实现类,线程不安全,效率高,能存储null的key和value * |------LinkedHashMap:保证在遍历map元素时,可以按照添加的顺序实现遍历 * 原因:在原有的HashMap底层结构基础上,添加了一对指针,指向前一个和后一个元素。 * 对于频繁的遍历操作,此类执行效率高于HashMap * |-----TreeMap:保证按照添加的key-value(键值对) 进行排序,实现排序遍历。此时考虑的key的自然or定制排序 * 底层使用红黑树 * |-----Hashtable: 作为古老的实现类:线程安全,效率低, 不能存储null的key和value * |------Properties:常用来处理配置文件。key和vaLue都是String类型 * * * HashMap的底层: 数组+链表jdk7及之前) * 数组+链表+红黑树(jdk 8>l * * 面试题: * 1.HashMap的底层实现原理? * 2.HashMap和 Hashtable的异同? * 3.CurrentHashMap 与 Hashtable的异同? (暂时不讲) * * * 二、Map结构的理解: * Map中的key:无序的、不可重复的,使用Set存储所有的Key --->Key所在的类要重写equals()和HashCode() (以HashMap为例) * Map中的value:无序的、可重复的,使用collection存储所有的value-->value所在的类重写equals() * 一个键值对: key-value构成了一个Entry对象。 * Map中的entry :无序的、不可重复的,使用set存储所有的entry。 * * 三、HashMap的底层实现原理? 以jdk7为例说明: * HashMap map = new HashMap( ): * 在实例化以后,底层创建了长度是16的一维数组Entry[]tabLe * 。...可能已经执行过多次put. . . * map.put( key1 , value1) : * 首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到在Entry数组中的存放位置。 * 如果此位置上的数据为空,此时的key1-value1添加成功。---情况1 * 如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在),比较key1和已经存在的一个或多个数据的哈希值: * 如果key1的哈希值与已经存在的数据的哈希值都不相同,此时key1-value1添加成功。---情况2 * 如果key1的哈希值和已经存在的某一个数据的哈希值相同,继续比较:调用key1所在类key1的equals(key2)方法,比较: * 如果equals()返回false:此时key1-value1添加成功。---情况3 * 如果equals()返回true:使用value1替换value2 * 补充:关于情况2和情况3: 此时key1-value1和原来的数据以链表的方式存储. * 在不断的添加过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空)时, * 默认的扩容方式:扩容为原来的容量的2倍,并将原有的数据复制过来. * *jdk8 相较于jdk7在底层实现方式的不同: * 1. new HashMap() :底层没有创建一个长度为16的数组 * 2.jdk8底层的数组是:Node[] 而非Entry[] * 3.首次调用put()的方法时间,底层创建长度为16的数组 * 4.jdk7底层结构只有: 数组+链表. jdk8中底层结构: 数组+链表+红黑树. * 当数组的某一个索引位置的元素以链表形式存在的数据个数大于8且当前数组的长度大于64时,此时此索引位置上的所有数据改 * 为使用红黑树存储. * * DEFAULT_INITIAL_CAPACITY : HashMap的默认容量,16 * DEFAULT_LOAD_FACTOR: HashMap的默认加载因子:0.75 * threshold:扩容的临界值,=容量*填充因子:16 * 0.75 =>12 * TREEIFY_THRESHOLD: Bucket中链表长度大于该默认值,转化为红黑树:8 * MIN_TREEIFY_CAPACITY:桶中的Node被树化时最小的hash表容量:64 * * * 四、LinkedHashMap 的底层实现原理(了解) * * 源码中: * static class Entry<K,V> extends HashMap. Node<K,V> { * Entry<K,V> before, after; //能够记录添加的元素的先后顺序 * Entry (int hash, K key, v value,Node<K,V> next) i * super( hash, key, value, next); * * * 五、Map中定义的方法: * 添加、删除、修改操作: * object put(object key,object value):将指定key-value添加到(或修改)当前map对象中 * void putAll(Map m):将m中的所有key-value对存放到当前map中 * object remove(object key):移除指定key的key-vaLue对,并返回valueVoid * clear():清空当前map中的所有数据 * * 元素查询的操作: * object get(Object key):获取指定key对应的value * boolean containsKey(object key):是否包含指定的Key * boolean containsValue(object value):是否包含指定的vaLue * int size():返回map 中key-value对的个数 * boolean isEmpty():判断当前map是否为空 * booLean equals(object obj):判断当前map和参数对象obj是否相等 * * 元视图操作的方法: * set keySet():返回所有key构成的Set集合 * collection values():返回所有value构成的Collection集合 * set entrySet():返回所有key-vaLue对构成的Set集合 * * *总结:常用方法: * 添加: * 删除: * 修改: * 查询: * 插入:不存在 * 长度: * 遍历: * * @author Dixon * @create 2022-06-15 20:32 */ public class MapTest { @Test public void test1(){ Map hashMap = new HashMap(); hashMap.put(null,null); } @Test public void test2(){ Map hashMap = new HashMap(); hashMap = new LinkedHashMap(); hashMap.put(123,"AA"); hashMap.put(345,"BB"); hashMap.put(12,"CC"); System.out.println(hashMap); } //Map中定义的方法-添加、删除、修改操作: @Test public void test3() { Map hashMap = new HashMap(); //1.object put(object key,object value):将指定key-value添加到(或修改)当前map对象中 hashMap.put("AA", 123); hashMap.put(45, 123); hashMap.put("BB", 56); hashMap.put("AA", 87); System.out.println(hashMap); //{AA=87, BB=56, 45=123} Map hashMap1 = new HashMap(); hashMap1.put("CC", 123); hashMap1.put("DD", 123); //2.void putAll(Map m):将m中的所有key-value对存放到当前map中 hashMap.putAll(hashMap1); System.out.println(hashMap); //{AA=87, BB=56, CC=123, DD=123, 45=123} //3. object remove(object key):移除指定key的key-vaLue对,并返回valueVoid Object cc = hashMap.remove("CC"); //如果key 是不存在 则返回value是null System.out.println(cc); //123 System.out.println(hashMap); //{AA=87, BB=56, DD=123, 45=123} //4.clear():清空当前map中的所有数据 hashMap.clear(); System.out.println(hashMap); //{} 与map = nuLL操作不同 System.out.println(hashMap.size()); //0 } //Map中定义的方法-元素查询的操作: @Test public void test4(){ Map hashMap = new HashMap(); hashMap.put("AA", 123); hashMap.put(45, 123); hashMap.put("BB", 56); hashMap.put("AA", 87); hashMap.put("Ad", 87); //1.object get(Object key):获取指定key对应的value System.out.println(hashMap.get(45)); //123 //2.boolean containsKey(object key):是否包含指定的Key boolean bb = hashMap.containsKey("BB"); System.out.println(bb); //true //3.boolean containsValue(object value):是否包含指定的value boolean b = hashMap.containsValue(123); System.out.println(b); //true //4.int size():返回map 中key-value对的个数 System.out.println(hashMap.size()); //4 //5.boolean isEmpty():判断当前map是否为空 System.out.println(hashMap.isEmpty()); //false // hashMap.clear(); // System.out.println(hashMap.isEmpty()); //true //5. booLean equals(object obj):判断当前map和参数对象obj是否相等元视图操作的方法 Map hashMap1 = new HashMap(); hashMap1.put("AA", 123); hashMap1.put(45, 123); hashMap1.put("BB", 56); hashMap1.put("AA", 87); hashMap1.put("Ad", 87); boolean equals = hashMap.equals(hashMap1); System.out.println(equals); //true } //元视图操作的方法: @Test public void test5(){ Map hashMap1 = new HashMap(); hashMap1.put("AA", 123); hashMap1.put(45, 124); hashMap1.put("BB", 56); hashMap1.put("AA", 88); hashMap1.put("Ad", 87); //1.set keySet():返回所有key构成的Set集合 Set set = hashMap1.keySet(); Iterator iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); }//AA BB Ad 45 System.out.println("-------------"); //2. collection values():返回所有value构成的Collection集合 for (Object value : hashMap1.values()) { System.out.println(value); }//88 56 87 124 System.out.println("-------------"); //3.set entrySet():返回所有key-vaLue对构成的Set集合、 Set set1 = hashMap1.entrySet(); for (Object o : set1) { System.out.println(o); //AA=88 BB=56 Ad=87 45=124 // 集合中的元素都是entry Map.Entry entry = (Map.Entry) o; System.out.println(entry.getKey() + "---->" + entry.getValue()); } } }
TreeMapTest
package com.collection.Map; import org.junit.Test; import java.util.Comparator; import java.util.TreeMap; /** * @author Dixon * @create 2022-06-17 20:07 */ public class TreeMapTest { // 向TreeMap中添加key-value,要求key必须是由同一个类创建的对象 // 因为要按照key进行排序:自然排序、定制排序 @Test //自然排序 public void test1(){ TreeMap map = new TreeMap( ); Student s1 = new Student("wjl", 29); Student s2 = new Student("dd", 21); Student s3 = new Student("dd1", 29); Student s4 = new Student("tts", 49); map.put(s1,98); map.put(s2,100); map.put(s3,60); map.put(s4,20); //先按照年龄从小大到排序,再按照名字从大到小排序 for (Object o : map.entrySet()) { System.out.println(o); } } @Test //定制排序 public void test2(){ TreeMap map = new TreeMap(new Comparator() { @Override public int compare(Object o1, Object o2) { if (o1 instanceof Student && o2 instanceof Student){ Student s1 = (Student)o1; Student s2 = (Student)o2; return Integer.compare(s1.getAge(),s2.getAge()); } throw new RuntimeException("类型不一致"); } }); Student s1 = new Student("wjl", 29); Student s2 = new Student("dd", 21); Student s3 = new Student("dd1", 29); Student s4 = new Student("tts", 49); map.put(s1,98); map.put(s2,100); map.put(s3,60); map.put(s4,20); for (Object o : map.entrySet()) { System.out.println(o); } } } class Student implements Comparable { private String name; private int age; public Student() { } public Student(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 o) { if (o instanceof Student){ Student student = (Student)o; int compare = Integer.compare(this.age, student.getAge()); if (compare ==0){ return -this.name.compareTo(student.getName()); }else { return compare; } } throw new RuntimeException("类型不一致"); } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
PropertiesTest
package com.collection.Map; import java.io.FileInputStream; import java.io.IOException; import java.util.Properties; /** * * Properties类是Hashtable的子类,该对象用于处理属性文件 * 由于属性文件里的key、value 都是字符串类型,所以Properties里的 key和 value都是字符串类型 * 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法 * @author Dixon * @create 2022-06-17 21:54 */ public class PropertiesTest { public static void main(String[] args) { // key和 value都是字符串类 FileInputStream fis = null; try { Properties pros = new Properties(); fis = new FileInputStream("高级语言/src/com/collection/Map/jdbc.properties"); pros.load(fis); //加载流对应的文件 String name = pros.getProperty("name"); String password = pros.getProperty("password"); System.out.println("name:" + name +", password:" + password); } catch (IOException e) { e.printStackTrace(); } finally { if (fis !=null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
posted on 2022-06-07 16:14 Dixon_Liang 阅读(30) 评论(0) 编辑 收藏 举报