5.1 Collection(单列),是一个接口
5.1.1 Collection
5.1.1.1 概述
- 是单列集合的顶层接口,他表示一组对象,这些对象也称为Collection的元素
- JDK不提供此接口的任何直接实现,他提供更具体的子接口如Set和List实现
创建Collection集合的对象
boolean add(E,e) 添加元素
- boolean remove(Object o) 从集合中移除指定元素
- void chear() 清空集合中的元素
- boolean contains(Object o) 判断集合中是否存在指定的元素
- boolean isEmpty() 判断集合是否为空
-
5.1.1.3 集合遍历
Iterator:迭代器,集合的专用遍历方式
- Iterator
iterator(): 返回此集合中的元素迭代器,通过集合的Iterator()方法得到 - 迭代器是通过集合的Iterator()方法得到的,所以我们说它是依赖于集合而存在的
- Iterator
- Iterator中常用方法
- E next():返回迭代中的下一个元素,通过迭代器获取元素时不能使用 集合.add() 修改集合,会抛出异常
- boolean hasNext():如果迭代具有更多元素,则返回true ```java import java.util.ArrayList; import java.util.Collection; import java.util.Iterator;
public class Demo {
public static void main(String[] args) {
Collection
Iterator<String> it = c.iterator();for(int i=0;i<3;i++)System.out.println(it.next());}
} 运行结果: [hello, world, java] hello world java
Process finished with exit code 0
<a name="Uzynf"></a>###<a name="dNPvl"></a>### 5.1.2 Set(不可重复)<a name="j2QvL"></a>#### 5.1.2.1 哈希值- 是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值- Object类中有一个方法可以获取对象的哈希值,**_public int hashCode()_** ;- 对象的哈希值特点- 同一个对象多次调用hashCode()方法返回的哈希值是相同的- 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同。<a name="Hc0f4"></a>#### 5.1.2.2 HashSet- 特点:- 底层数据结构就是哈希表,本质就是new了一个HashMap- 对集合的迭代顺序不做任何保证,也就是说不保证存储和取出的元素顺序一致- 没有带索引的方法,所以不能使用普通for循环遍历- 由于是Set集合,所以是不包含重复元素的集合- LinkedHashSet集合特点:- 哈希表和链表实现的Set接口,具体可预测的迭代次序- 由于链表保证元素有序,也就是说元素的存储和取出顺序是一致的- 由哈于希表保证元素唯一,也就是没有重复的元素<a name="wg0F6"></a>#### 5.1.2.3 TreeSet- 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法。- TreeSet():根据其元素的自然排序进行排序,自然排序Comparable的使用:- 存储学生对象并遍历,创建TreeSet集合使用无参构造方法。例:```java/*按照年龄从小到大排序,年龄相同时,按照姓名字母顺序排序*/import java.util.TreeSet;public class Demo {public static void main(String[] args) {TreeSet<Student> ts = new TreeSet<Student>() ;Student s1 = new Student("xishi",22);Student s2 = new Student("wangzhaojun",25);Student s3 = new Student("diaochan",28);Student s4 = new Student("yangyuhuan",21);Student s5 = new Student("ahangsannnnnn",20);Student s6 = new Student("yhangyuhuan",20);ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);ts.add(s5);ts.add(s6);for(Student s : ts){System.out.println(s.getName()+","+s.getAge());}}}********************************************************************public class Student implements Comparable<Student>{private String name ;private Integer age ;public Student() {}public Student(String name, Integer age) {this.name = name;this.age = age;}public String getName() { return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic int compareTo(Student o) {int num1 = this.age-o.age ;int num2 = num1==0?this.name.compareTo(o.name):num1 ;return num2 ;}}运行结果:ahangsannnnnn,20yhangyuhuan,20yangyuhuan,21xishi,22wangzhaojun,25diaochan,28Process finished with exit code 0
- 结论:用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的。自然排序就是让元素所属的类实现Comparable接口,重写compareTo方法。重写方法时一定要注意排序规则必须按照要求的主要条件和次要条件来写。
/*用TreeSet结合存储多个学生信息,按照总分从高到低排,若总分一样,比语文成绩,若语文成绩一样比较名字的Unicode值,越小越靠前*/import java.util.TreeSet;public class Demo {public static void main(String[] args) {TreeSet<Student> ts = new TreeSet<Student>() ;Student s1 = new Student("小王",20,20) ; //unicode值: 王 --> 29579Student s2 = new Student("小张",20,20) ; //unicode值: 张 --> 24352Student s3 = new Student("小黑",50,50) ;Student s4 = new Student("小白",90,90) ;Student s5 = new Student("小绿",89,91) ; //unicode值: 绿 --> 32511Student s6 = new Student("小一",89,91) ; //unicode值: 一 --> 19968ts.add(s1) ;ts.add(s2) ;ts.add(s3) ;ts.add(s4) ;ts.add(s5) ;ts.add(s6) ;for(Student s : ts){s.show();}}}******************************************************************************public class Student implements Comparable<Student>{private String name ;private int chineseScore ;private int mathScore ;public Student() {}public Student(String name, int chineseScore, int mathScore) {this.name = name;this.chineseScore = chineseScore;this.mathScore = mathScore;}public String getName() { return name;}public void setName(String name) { this.name = name;}public int getChineseScore() {return chineseScore;}public void setChineseScore(int chineseScore) {this.chineseScore = chineseScore;}public int getMathScore() {return mathScore;}public void setMathScore(int mathScore) {this.mathScore = mathScore;}public void show(){System.out.println(name+","+chineseScore+","+mathScore);}@Overridepublic int compareTo(Student s) {int cScore = this.chineseScore-s.chineseScore ;int num = s.chineseScore+s.mathScore-this.chineseScore-this.mathScore ;int num2 = num==0?cScore:num ;int num3 = num2==0?this.name.compareTo(s.name):num2 ;return num3;}}运行结果:小一,89,91小绿,89,91小白,90,90小黑,50,50小张,20,20小王,20,20Process finished with exit code 0
- TreeSet(Comparator comparator):根据指定的比较器进行排序,比较器排序Comparator的使用: ```java / 按照年龄从小到大排序,年龄相同时,按照姓名字母顺序排序 /
import java.util.Comparator; import java.util.TreeSet;
public class Demo { public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {@Overridepublic int compare(Student s1, Student s2) {int num = s1.getAge()-s2.getAge() ;int num2 = num==0?s1.getName().compareTo(s2.getName()):num ;return num2;}}) ;Student s1 = new Student("xishi",22);Student s2 = new Student("wangzhaojun",25);Student s3 = new Student("diaochan",28);Student s4 = new Student("yangyuhuan",21);Student s5 = new Student("ahangsannnnnn",20);Student s6 = new Student("yhangyuhuan",20);ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);ts.add(s5);ts.add(s6);for(Student s : ts){System.out.println(s.getName()+","+s.getAge());}}
}
public class Student { private String name ; private Integer age ;
public Student() {}public Student(String name, Integer age) {this.name = name;this.age = age;}public String getName() { return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
} 运行结果:(和上面的一样) ahangsannnnnn,20 yhangyuhuan,20 yangyuhuan,21 xishi,22 wangzhaojun,25 diaochan,28
Process finished with exit code 0
- 结论:用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的。比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compareTo()方法。- 没有带索引的方法,所以不能使用普通for循环遍历- 由于是set集合,所以不包含重复元素的集合<a name="vBQ02"></a>### 5.1.3 List(可重复,有序集合)<a name="u0aTn"></a>#### 5.1.3.1 ArrayList<E>- 可调整大小的数组实现,底层数据结构是数组,查询快,增删慢- 构造方法和添加方法- _**public ArrayList()**_ 创建一个空白集合对象- _**public boolean add(E e)**_ 将指定元素追加到此集合的末尾- _**public void add(int index,E element) **_ 在此集合中的指定位置插入指定元素- 常用方法:- _**public boolean remove(Object o) **_删除指定元素,返回是否删除成功- _**public E remove(int index) **_ 删除指定元素,返回被删除的元素- _**public E set(int index,E element)**_ 修改指定索引处的元素,返回被修改的元素- _**public E get(int index)**_ 返回指定索引处的元素- _**public int size() **_返回集合中元素的个数<a name="Tp5dh"></a>#### 5.1.3.2 LinkedList<E>- 底层数据结构是链表,查询慢,增删慢- 特有功能:- _**public void addFirst(E e) **_在该列表开肉插入指定的元素- _**public void addLast(E e)**_ 将指定的元素追加到此列表的末尾- _**public E getFirst()**_ 返回此列表中的第一个元素- _**public E getLast() **_ 返回此列表中的最后一个元素- _**public E removeFirst()**_ 从此列表中删除并返回第一个元素- _**public E removeLast() **_ 从此列表中删除并返回最后一个元素<a name="LV3DI"></a>#### 5.1.3.3 ListIterator<E>- 列表迭代器- 通过List集合的ListIterator()方法得到,所以说它是List结合特有的迭代器- 用于允许程序员沿任何一方向遍历列表迭代器,在迭代期间修改列表,并获得列表中迭代器的当前位置- 常用方法- _**E next() **_ 返回迭代中下一个元素- _**boolean hasNext() **_ 如果迭代具有更多元素,则返回true- _**E previous()**_ 返回列表中的上一个元素- _**boolean hasPrevious() **_ 如果此列表迭代器在相反方法遍历列表时具有更多元素,则返回true- _**void add(E e)**_ 将指定的元素插入列表<a name="bW63n"></a>#### 5.1.3.4 增强for循环- 简化数组和Collection集合的遍历```javapublic class Demo {public static void main(String[] args) {Collection<String> c = new ArrayList<>() ;c.add("hello");c.add("world");c.add("java");System.out.println(c);for(String s : c)System.out.println(s);}}运行结果:[hello, world, java]helloworldjavaProcess finished with exit code 0
5.2 Collections 概述和使用
- 是针对集合操作的工具类
- 常用方法:
- public static
> void sort(List (有重载)将指定的列表升序排序list) - public static void reverse(List<?> list) 反转指定列表中的元素排序
- public static void shuffle(List<?> list) 使用默认的随机源随机排列指定的列表 ```java import java.util.*;
- public static
public class Demo { public static void main(String[] args) {
List<Integer> list = new ArrayList<>() ;list.add(10) ;list.add(30) ;list.add(90) ;list.add(80) ;list.add(50) ;list.add(20) ;Collections.sort(list);System.out.println(list);Collections.reverse(list) ;System.out.println(list);Collections.shuffle(list) ;System.out.println(list);}
} 运行结果: [10, 20, 30, 50, 80, 90] [90, 80, 50, 30, 20, 10] [50, 30, 90, 20, 10, 80]
Process finished with exit code 0
```java/*例子:ArrayList存储学生对象并排序需求:使用Collections对ArrayList进行排序;按照年龄从小到大,年龄相同时,按照姓名字母进行排序*/import java.util.*;public class Demo {public static void main(String[] args) {List<Student> arr = new ArrayList<>() ;Student s1 = new Student("zhangsan",30) ;Student s2 = new Student("lisi",35) ;Student s3 = new Student("wangwu",33) ;Student s4 = new Student("liuliu",33) ;arr.add(s1);arr.add(s2);arr.add(s3);arr.add(s4);Collections.sort(arr, new Comparator<Student>() {@Overridepublic int compare(Student s1, Student s2) {int num1 = s1.getAge()-s2.getAge() ;int num2 =num1==0?s1.getName().compareTo(s2.getName()):num1 ;return num2 ;}});for(Student s:arr){System.out.println(s.getName()+","+s.getAge());}}}*****************************************************************************public class Student {private String name ;private Integer age ;public Student() {}public Student(String name, Integer age) {this.name = name;this.age = age;}public String getName() { return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}}运行结果:zhangsan,30liuliu,33wangwu,33lisi,35Process finished with exit code 0
5.3 Map集合概述(双列)
- Interface Map
K:键的类型,V:值的类型 - 将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值。
基本方法:
- V put(K key,value) 添加元素
- V remove(Object key) 根据键删除键值对元素
- void clear() 清空Map集合
- boolean containsKey(Object key) 判断集合是否包含指定的键
- boolean containsValue(Object Value) 判断集合是否包含指定的值
- boolean isEmpty() 判断集合是否为空
- int size() 集合的长度,也就是集合中键值对的个数
import java.util.* ;public class Demo {public static void main(String[] args) {Map<String,String> map = new HashMap<>() ;map.put("001","111") ;map.put("002","222");map.put("003","333");map.put("004","444");// map.remove("003");map.clear();System.out.println(map.isEmpty());System.out.println(map.size());// System.out.println(map.containsValue("003"));// System.out.println(map.containskey("003"));System.out.println(map);}}
获取方法:
- V get(Object key) 根据键获取
- Set
keySet() 获取所有键的集合 - Collection
values() 获取所有值的集合 Set
> entrySet() 获取所有键值对对象集合;用getKey()得到键,用getValue()得到值。 ```java import java.util.* ; public class Demo { public static void main(String[] args) {Map
map = new HashMap () ; map.put(“001”,”111”) ; map.put(“002”,”222”); map.put(“003”,”333”); map.put(“004”,”444”); System.out.println(map.get(“0011”)); System.out.println(map.get(“001”)); System.out.println(“————-“); Collection
values = map.values(); for(String i : values){ System.out.print(i+" ");
} System.out.println(); Set
keySet = map.keySet() ; for(String i : keySet){ System.out.print(i+" ");
} System.out.println(); System.out.println(“————-“); Set
> entrySet = map.entrySet() ; for(Map.Entry me : entrySet){ System.out.println(me.getKey()+","+me.getValue());
}
} } 运行结果: null 111
111 222 333 444
001 002 003 004
001,111 002,222 003,333 004,444
Process finished with exit code 0
- 例子:```javaimport java.util.* ;public class Demo {public static void main(String[] args) {HashMap<String,Student> map = new HashMap<String,Student>() ;Student s1 = new Student("111",66,33) ;Student s2 = new Student("222",67,34) ;Student s3 = new Student("333",68,35) ;map.put("001",s1) ;map.put("002",s2);map.put("003",s3);Set<String> setKey = map.keySet() ;for(String key : setKey){System.out.print(key+",");map.get(key).show();}System.out.println("----------------");Set<Map.Entry<String,Student>> entrySet = map.entrySet() ;for(Map.Entry<String,Student> me : entrySet){System.out.print(me.getKey()+",");me.getValue().show();}}}***********************************************************************************public class Student {private String name ;private int chineseScore ;private int mathScore ;public Student() {}public Student(String name, int chineseScore, int mathScore) {this.name = name;this.chineseScore = chineseScore;this.mathScore = mathScore;}public String getName() { return name; }public void setName(String name) { this.name = name; }public int getChineseScore() { return chineseScore; }public void setChineseScore(int chineseScore) { this.chineseScore = chineseScore; }public int getMathScore() { return mathScore; }public void setMathScore(int mathScore) { this.mathScore = mathScore; }public void show(){System.out.println(name+","+chineseScore+","+mathScore);}}运行结果:002,222,67,34003,333,68,35----------------001,111,66,33002,222,67,34003,333,68,35Process finished with exit code 0
import java.util.* ;public class Demo {public static void main(String[] args) {HashMap<Student,String> map = new HashMap<Student,String>() ;Student s1 = new Student("111",66,33) ;Student s2 = new Student("222",67,34) ;Student s3 = new Student("333",68,35) ;Student s4 = new Student("333",68,35) ;map.put(s1,"111") ;map.put(s2,"222") ;map.put(s3,"333") ;map.put(s4,"444") ;Set<Student> s = map.keySet() ;for(Student ss : s){System.out.println(ss.getName()+","+ss.getChineseScore()+","+ss.getMathScore()+"-->"+map.get(ss));}}}***********************************************************************************import java.util.Objects;public class Student {private String name ;private int chineseScore ;private int mathScore ;public Student() {}public Student(String name, int chineseScore, int mathScore) {this.name = name;this.chineseScore = chineseScore;this.mathScore = mathScore;}public String getName() { return name; }public void setName(String name) { this.name = name; }public int getChineseScore() { return chineseScore; }public void setChineseScore(int chineseScore) { this.chineseScore = chineseScore; }public int getMathScore() { return mathScore; }public void setMathScore(int mathScore) { this.mathScore = mathScore; }public void show(){System.out.println(name+","+chineseScore+","+mathScore);}//重写后比的是对象里面的属性值,不然比的是地址值,就会出现两个 333,68,35@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return chineseScore == student.chineseScore && mathScore == student.mathScore && Objects.equals(name, student.name);}@Overridepublic int hashCode() {return Objects.hash(name, chineseScore, mathScore);}}运行结果:111,66,33-->111333,68,35-->444222,67,34-->222Process finished with exit code 0
/* ArrayList嵌套HashMap */import java.util.* ;public class Demo {public static void main(String[] args) {ArrayList<HashMap<String,String>> ah =new ArrayList<>();HashMap<String,String> hm1 = new HashMap<String,String>() ;HashMap<String,String> hm2 = new HashMap<String,String>() ;HashMap<String,String> hm3 = new HashMap<String,String>() ;hm1.put("001","111");hm2.put("002","222");hm3.put("003","333");ah.add(hm1);ah.add(hm2);ah.add(hm3);for(HashMap<String,String> hm:ah){Set<String> setKey = hm.keySet() ;for (String key:setKey){System.out.println(key+","+hm.get(key));}}}}
/* HashMap嵌套ArrayList */import java.util.* ;public class Demo {public static void main(String[] args) {HashMap<String,ArrayList<String>> hashMap = new HashMap<String,ArrayList<String>>() ;ArrayList<String> array1 = new ArrayList<String>() ;ArrayList<String> array2 = new ArrayList<String>() ;ArrayList<String> array3 = new ArrayList<String>() ;array1.add("11");array1.add("111");array2.add("22");array2.add("222");array3.add("33");array3.add("333");hashMap.put("001",array1);hashMap.put("002",array2);hashMap.put("003",array3);Set<String> setKey = hashMap.keySet() ;for(String key : setKey){ArrayList<String> list = hashMap.get(key) ;System.out.print(key);for(String s :list){System.out.print(" "+s);}System.out.println();}}}运行结果:001 11 111002 22 222003 33 333
/* 统计字符串中每个字符出现的次数 */import java.util.* ;public class Demo {public static void main(String[] args) {Scanner sc = new Scanner(System.in) ;String line = sc.nextLine() ;TreeMap<Character,Integer> tm = new TreeMap<>() ;for(int i=0;i<line.length();i++){char key = line.charAt(i) ; //读取对应的索引字符Integer value = tm.get(key) ; //把字符作为键,来获取值if(value == null){tm.put(key,1) ; //如果值为空就是该字符没有在集合中出现过,创建一个键值对}else {value++ ;tm.put(key,value);}}StringBuilder sb = new StringBuilder();Set<Character> setKey = tm.keySet() ;for(Character key : setKey){sb.append(key).append("-->"+tm.get(key)+"\n") ;}System.out.println(sb.toString());}}运行结果:;-->1a-->4d-->1f-->1g-->4h-->1i-->1j-->1l-->1s-->1Process finished with exit code 0
5.4 泛型
- 概述:是JDK5中引入的特性,他提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型,他的本质是参数化类型,也就是所操作的数据类型被指定为一个参数。提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾明思义,就是 将 类型由原来的具体的类型参数化,然后在使用/调用是传入具体的类型。这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口。
- 格式:
- <类型>:指定一种类型的格式。这里的类型可以看成是形参。
- <类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参。
- 将来具体调用的时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型。
- 好处:把运行时期的问题提前到了编译期间;避免了强制类型转换。
泛型类:格式:修饰符 class 类名<类型>{}
```java public class Demo { public static void main(String[] args) {Generic<String> name = new Generic<>() ;name.setT("小红");Generic<Integer> age = new Generic<>() ;age.setT(99);System.out.println(name.getT()+","+age.getT());
} }
public class Generic
public T getT() { return t; }public void setT(T t) { this.t = t; }
} 运行结果: 小红,99
Process finished with exit code 0
- 泛型方法:格式:修饰符<类型> 返回值类型 方法名(类型 变量名)```javapublic class Demo {public static void main(String[] args) {Generic name = new Generic() ;name.show("sss");name.show(666);}}***********************************************************************************public class Generic {public <T> void show(T t){System.out.println(t);}}运行结果:sss666Process finished with exit code 0
- 泛型接口:格式:修饰符 interface 接口名<类型>
```java
public class Demo {
public static void main(String[] args) {
} }Generic<String> name = new GenericImpl<String>() ;name.show("sss");Generic<Integer> age = new GenericImpl<>();age.show(666);
public interface Generic
public class GenericImpl
- 类型通配符:- 为了表示各种泛型List的父类,可以使用类型通配符 <?>- List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型。- 这种通配符的List仅表示他是各种泛型的父类,并不能把元素添加到其中。```javaimport java.util.* ;public class Demo {public static void main(String[] args) {List<?> list1 = new ArrayList<Object>() ;List<?> list2 = new ArrayList<Number>() ;List<?> list3 = new ArrayList<String>() ;}}
- 如果不希望List<?>是任何泛型List的父类,只希望它代表某一类泛型LIst的父类,可以使用类型通配符的上限。
- 类型通配符上限:<? extend 类型>
- List<? extends Number> : 表示的类型是Number或者其子类型
- 除了可以指定上限还可以指定下限,
- 类型通配符下限 <? super 类型>
- List<? super Number>:表示的类型是Number或者其父类
- 可变参数(可变参数又称个数可变,用作方法的形参出现,那么方法参数个数就是可变的了)
- 格式:修饰符 返回值类型 方法名(数据类型… 变量名)
- 这里的变量是一个数组。如果一个方法有多个参数,包含可变参数,可变参数要放在最后面
public class Demo {public static void main(String[] args) {System.out.println(sum(10,20)); //30System.out.println(sum(10,20,30)); //60System.out.println(sum(10,20,30,40)); //100System.out.println(sum(10,20,30,40,50)); //150System.out.println(sum(10,20,30,40,50,60)); //210System.out.println(sum(10,20,30,40,50,60,70)); //280}public static int sum(int... a){int sum=0 ;for(int i : a){sum+=i ;}return sum ;}public static int sum(int a,int b,int c){return a+b+c ;}public static int sum(int a,int b,int c,int d){return a+b+c+d ;}}
