Java 基础(集合)
集合框架的概述
1.集合是对多个数据进行存储操作的结构,简称Java容器。
说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中)
集合都是以数组和链表为基础实现的。
集合框架
|----Collection接口:单列集合,用来存储一个一个的对象 |----List接口:存储有序的、可重复的数据。 -->“动态”数组 |----ArrayList:作为List接口的主要实现类:线程不安全的,效率高;底层使用Object[] elementData存储 |----LinkedList:对于频繁的插入,删除操作,使用此类效率比ArrayList高;底层使用双向链表存储 |----Vector:作为List接口的古老实现类;线程安全的,效率低;底层使用Object[]存储 |----Set接口:存储无序的、不可重复的数据 -->高中讲的“集合” |----HashSet:作为Set接口的主要实现类;线程不安全的;可以存储null值 |----LinkedHashSet:作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序对于频繁的遍历操作,LinkedHashset效率高于HashSet。 |----TreeSet:可以按照添加对象的指定属性,进行排序。 |----Map接口:双列集合,用来存储一对(key - value)一对的数据 -->高中函数:y = f(x) |----HashMap、LinkedHashMap、TreeMap、Hashtable、Properties
List接口
CollectionTest.java
package com.klvchen.java2; import org.junit.Test; import java.util.ArrayList; import java.util.Collection; import java.util.Date; public class CollectionTest { @Test public void test1(){ Collection col1 = new ArrayList(); // add(Object e): 将元素e添加到集合 col1中 col1.add("AA"); col1.add("BB"); col1.add(123); col1.add(new Date()); //size(): 获取添加的元素的个数 System.out.println(col1.size()); //addAll(); Collection coll1 = new ArrayList(); coll1.add(456); coll1.add("CC"); col1.addAll(coll1); System.out.println(col1.size()); System.out.println(col1); //clear(): 清空集合元素 col1.clear(); //isEmpty():判断当前集合是否为空 System.out.println(col1.isEmpty()); } }
CollectionTest1.java
package com.klvchen.java2; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; public class CollectionTest1 { @Test public void test1(){ Collection col1 = new ArrayList(); col1.add(123); col1.add(456); col1.add(new String("Tom")); col1.add(false); col1.add(new Person("Jerry", 20)); // Person p = new Person("jerry", 20); // col1.add(p); //1.contains(Object obj):判断当前集合中是否包含obj //我们会在判断时调用obj对象所在类的equals()。 boolean contains = col1.contains(123); System.out.println(contains); //true System.out.println(col1.contains(new String("Tom"))); //true // System.out.println(col1.contains(p)); //true System.out.println(col1.contains(new Person("Jerry",20))); //2.containsAll(Collection coll1):判断形参coll1中的所有元素释放都存在于当前集合中 Collection coll1 = Arrays.asList(123, 456); System.out.println(col1.containsAll(coll1)); } @Test public void test2(){ //3.remove(Object obj): 从当前集合中移除obj元素 Collection col1 = new ArrayList(); col1.add(123); col1.add(456); col1.add(new Person("Jerry", 20)); col1.add(new String("Tom")); col1.add(false); col1.remove(1234); System.out.println(col1); col1.remove(new Person("Jerry", 20)); System.out.println(col1); } @Test public void test3(){ Collection col1 = new ArrayList(); col1.add(123); col1.add(456); col1.add(new Person("Jerry", 20)); col1.add(new String("Tom")); col1.add(false); //5.retainAll(Collection coll1): 交集:获取当前集合和coll1集合的交集,并返回当前集合 // Collection coll1 = Arrays.asList(123, 456, 789); // col1.retainAll(coll1); // System.out.println(col1); //6.equals(Object obj):要想返回true,需要当前集合和形参集合的元素都相同,顺序也要一样。 Collection coll1 = new ArrayList(); coll1.add(123); coll1.add(456); coll1.add(new Person("Jerry", 20)); coll1.add(new String("Tom")); coll1.add(false); System.out.println(col1.equals(coll1)); } @Test public void test4(){ Collection col1 = new ArrayList(); col1.add(123); col1.add(456); col1.add(new Person("Jerry", 20)); col1.add(new String("Tom")); col1.add(false); //7.hashCode(): System.out.println(col1.hashCode()); //8.集合 --> 数组 toArray() Object[] arr = col1.toArray(); for (int i = 0; i < arr.length; i++){ System.out.println(arr[i]); } //数组 --> 集合: 调用Arrays类的静态方法 asList() List<String> list = Arrays.asList(new String[]{"AA", "BB", "CC"}); System.out.println(list); List<int[]> arr1 = Arrays.asList(new int[]{123, 456}); System.out.println(arr1); System.out.println(arr1.size()); List arr2 = Arrays.asList(123, 456); System.out.println(arr2); List arr3 = Arrays.asList(new Integer[]{123, 456}); System.out.println(arr3.size()); } }
IteratorTest
package com.klvchen.java2; import org.junit.Test; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; /* 集合元素的遍历操作,使用迭代器Iterator接口 1.内部的方法: hasNext() 和 next() 2.集合对象每次调用 iterator() 方法都得到一个全新的迭代器对象, 默认游标都在集合的第一个元素之前。 3.内部定义了 remove(),可以在遍历的时候,删除集合中的元素,此方法不同于集合直接调用remove() */ public class IteratorTest { //iterator(): 返回Iterator接口的实例,用于遍历集合元素 @Test public void test1(){ Collection col1 = new ArrayList(); col1.add(123); col1.add(456); col1.add(new Person("Jerry", 20)); col1.add(new String("Tom")); col1.add(false); Iterator iterator = col1.iterator(); //方式一 // 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()); //报异常:java.util.NoSuchElementException // System.out.println(iterator.next()); //方式二:不推荐 // for (int i = 0; i < col1.size(); i++){ // System.out.println(iterator.next()); // } //方式三:推荐 while (iterator.hasNext()){ System.out.println(iterator.next()); } } @Test public void test2(){ Collection col1 = new ArrayList(); col1.add(123); col1.add(456); col1.add(new Person("Jerry", 20)); col1.add(new String("Tom")); col1.add(false); //删除集合中"Tom" Iterator iterator = col1.iterator(); while (iterator.hasNext()){ Object obj = iterator.next(); if ("Tom".equals(obj)){ iterator.remove(); } } //遍历集合 iterator = col1.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } }
ForTest.java
package com.klvchen.java; import org.junit.Test; import java.util.ArrayList; import java.util.Collection; public class ForTest { @Test public void test1(){ Collection col1 = new ArrayList(); col1.add(123); col1.add(456); col1.add(new Person("Jerry", 20)); col1.add(new String("Tom")); col1.add(false); //for(集合元素的类型 局部变量 : 集合对象) //内部仍然调用了迭代器 for(Object obj : col1){ 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 (int i = 0; i < arr.length; i++){ // arr[i] = "GG"; //} //方式二: 增强for循环 for (String s : arr){ s = "GG"; } for (int i = 0; i< arr.length; i++){ System.out.println(arr[i]); } } }
ListTest.java
package com.klvchen.java; import org.junit.Test; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; public class ListTest { @Test public void test3(){ ArrayList list = new ArrayList(); list.add(123); list.add(456); list.add("AA"); //方式一: Iterator迭代器方式 Iterator iterator = list.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } System.out.println("********************"); //方式二: for(Object obj: list){ System.out.println(obj); } System.out.println("********************"); //方式三 for (int i = 0; i < list.size(); i++){ System.out.println(list.get(i)); } } @Test public void test2(){ ArrayList list = new ArrayList(); list.add(123); list.add(456); list.add("AA"); list.add(new Person("Tom", 12)); list.add(456); //int indexOf(Object obj):返回obj在集合中首次出现的位置。如果不存在,返回-1 int index = list.indexOf(456); System.out.println(index); //int lasterIndexOf(Object obj):返回obj在当前集合中末次出现的位置 System.out.println(list.lastIndexOf(456)); //Object remove(int index):移除指定位置的元素,并返回此元素 Object obj = list.remove(0); System.out.println(obj); System.out.println(list); //Object set(int index, Object ele):设置指定index位置的元素为ele list.set(1, "CC"); System.out.println(list); //List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的左闭右开集合 List subList = list.subList(2, 4); System.out.println(subList); System.out.println(list); } @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); //void add(int index, Object ele): 在index位置插入ele元素 list.add(1, "BB"); System.out.println(list); //boolean addAll(int index, Collection eles): 从index位置开始将eles中的所有元素 List list1 = Arrays.asList(1, 2, 3); //list.add(list1); list.addAll(list1); System.out.println(list.size()); //Object get(int index): 获取指定index位置的元素 System.out.println(list.get(0)); } }
ListExer.java
package com.klvchen.exer; import org.junit.Test; import java.util.ArrayList; import java.util.List; public class ListExer { @Test public void testListRemove(){ List list = new ArrayList(); list.add(1); list.add(2); list.add(3); updateList(list); System.out.println(list); } private void updateList(List list){ //list.remove(2); list.remove(new Integer(2)); } }
set接口
set接口:存储无序的,不可重复的数据 --> 高中讲的 "集合"
- HashSet: 作为Set接口的主要实现类;线程不安全的;可以存储null值
- LinkedHashSet: 作为HashSet的子类;遍历其内部数据时,可以按照添加的顺序遍历,对于频繁的遍历操作,LinkedHashSet效率高于HashSet。
- TreeSet: 可以按照添加对象的指定属性,进行排序。
Set接口中没有额外定义新的方法,使用的都是collection中声明过的方法。
要求:向Set(主要指:HashSet、LinkedHashSet)中添加的数据,其所在的类一定要重写hashCode()和equals()
要求:重写的hashCode()和equals()尽可能保持一致性:相等的对象必须具有相等的散列码
重写两个方法的小技巧:对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。
User.java
package com.klvchen.java2; public class User implements Comparable { private String name; private int age; public User() { } public User(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 String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public boolean equals(Object o) { System.out.println("User equals()....."); if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (age != user.age) return false; return name != null ? name.equals(user.name) : user.name == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + age; return result; } //按照姓名从大到小排列,年龄从小到大排列 @Override public int compareTo(Object o) { if(o instanceof User){ User user = (User) o; //return this.name.compareTo(user.name); int compare = -this.name.compareTo(user.name); if (compare != 0){ return compare; }else { return Integer.compare(this.age, user.age); } }else { throw new RuntimeException("输入的类型不匹配"); } } }
SetTest.java
package com.klvchen.java2; /* Set: 存储无序的,不可重复的数据 1. 无序性: 不等于随机性。存储的数据在底层数组中并非按照数组索引的顺序添加,而是根据数据的哈希值决定的。 2. 不可重复性: 保证添加的元素按照equals()判断时,不能返回true。即:相同的元素只能添加一个。 添加元素的过程:以HashSet为例: 我们向HashSet中添加元素a,首先调用元素a所在类的hashCode()方法,计算元素a的哈希值,此哈希值接着通过 某种算法计算出在HashSet底层数组中的存放位置(即为:索引位置),判断数组此位置上是否已经有元素: 1. 如果此位置上没有其他元素,则元素a添加成功。 2. 如果此位置上有其他元素b(或以链表形式存在的多个元素),则比较元素a与元素b的hash值: 如果hash值不相同,则元素a添加成功。 如果hash值相同,进而需要调用元素a所在类的equlas()方法: equals()返回true,元素α添加失败 equals()返回false,则元素a添加成功。 对于添加成功的情况:元素与已经存在指定索引位置上数据以链表的方式存储。 jdk 7 :元素a放到数组中,指向原来的元素。 jdk 8 :原来的元素在数组中,指向元素a 总结:七上八下 */ import org.junit.Test; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; public class SetTest { @Test public void test1(){ Set set = new HashSet(); set.add(456); set.add(123); set.add("AA"); set.add("CC"); set.add(new User("Tom", 12)); set.add(new User("Tom", 12)); set.add(129); Iterator iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } //LinkedHashSet的使用 //LinkedHashset作为HashSet的教据还维护了两个引用,记录此数据前一个数据和后一个数据 @Test public void test2(){ Set set = new LinkedHashSet(); set.add(456); set.add(123); set.add("AA"); set.add("CC"); set.add(new User("Tom", 12)); set.add(new User("Tom", 12)); set.add(129); Iterator iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } }
TreeSetTest.java
package com.klvchen.java2; import org.junit.Test; import java.util.Comparator; import java.util.Iterator; import java.util.TreeSet; /* 1.向TreeSet中添加的数据,要求是相同类的对象。 2.两种排序方式:自然排序和定制排序 3.自然排序中,比较两个对象是否相同的标准为: compareTo()返回0.不再是equals() 4.定制排序中,比较两个对象是否相同的标准为: comparq()返回0.不再是equals(). */ public class TreeSetTest { @Test public void test2(){ Comparator com = new Comparator() { @Override public int compare(Object o1, Object o2) { if (o1 instanceof User && o2 instanceof User){ User u1 = (User) o1; User u2 = (User) o2; return Integer.compare(u1.getAge(), u2.getAge()); }else { throw new RuntimeException("输入的类型不匹配"); } } }; TreeSet set = new TreeSet(com); set.add(new User("Tom", 12)); set.add(new User("Jerry", 32)); set.add(new User("Jim", 2)); set.add(new User("Mike", 65)); set.add(new User("Jack", 33)); set.add(new User("Jack", 56)); Iterator iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } @Test public void test1(){ TreeSet set = new TreeSet(); //不能添加不同类型的对象 //set.add(34); //set.add(-34); //set.add(43); //set.add(11); //set.add(8); //例子二: set.add(new User("Tom", 12)); set.add(new User("Jerry", 32)); set.add(new User("Jim", 2)); set.add(new User("Mike", 65)); set.add(new User("Jack", 33)); Iterator iterator = set.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } }
Person.java
package com.klvchen.exer; public class Person { private int id; public String name; public Person(int id, String name) { this.id = id; this.name = name; } public Person() { } 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; Person person = (Person) o; if (id != person.id) return false; return name != null ? name.equals(person.name) : person.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 + '\'' + '}'; } }
CollectionTest.java
package com.klvchen.exer; import org.junit.Test; import java.util.HashSet; public class CollectionTest { @Test public void test3(){ HashSet set = new HashSet(); Person p1 = new Person(1001, "AA"); Person p2 = new Person(1002, "BB"); set.add(p1); set.add(p2); System.out.println(set); p1.name = "CC"; set.remove(p1); System.out.println(set); set.add(new Person(1001, "CC")); System.out.println(set); set.add(new Person(1001, "AA")); System.out.println(set); } }