集合概述
当需要在Java程序中记录单个数据内容时,则声明一个变量。
当需要在Java程序中记录多个类型相同的数据内容时,声明一个一维数组。
当需要在Java程序中记录多个类型不同的数据内容时,则创建一个对象。
当需要在Java程序中记录多个类型相同的对象数据时,创建一个对象数组。
当需要在Java程序中记录多个类型不同的对象数据时,则准备一个集合。
集合的框架结构
集合的框架结构 Java中集合框架顶层框架是:java.util.Collection集合 和 java.util.Map集合。
其中Collection集合中存取元素的基本单位是:单个元素。
其中Map集合中存取元素的基本单位是:单对元素。
Collection集合
java.util.Collection接口是List接口、Queue 接口以及Set接口的父接口,因此该接口里定义的方法 既可用于操作List集合,也可用于操作Queue集合和Set集合。
常用的方法
方法如下:
public boolean add(E e)
: 把给定的对象添加到当前集合中 。
public void clear()
:清空集合中所有的元素。
public boolean remove(E e)
: 把给定的对象在当前集合中删除。
public boolean contains(E e)
: 判断当前集合中是否包含给定的对象。
public boolean isEmpty()
: 判断当前集合是否为空。
public int size()
: 返回集合中元素的个数。
public Object[] toArray()
: 把集合中的元素,存储到数组中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public static void main(String[] args) { Collection<String> coll = new ArrayList<String>(); coll.add("小李广"); coll.add("扫地僧"); coll.add("石破天"); System.out.println(coll); System.out.println("判断 扫地僧 是否在集合中"+coll.contains("扫地僧")); System.out.println("删除石破天:"+coll.remove("石破天")); System.out.println("操作之后集合中元素:"+coll); System.out.println("集合中有"+coll.size()+"个元素"); Object[] objects = coll.toArray(); for (int i = 0; i < objects.length; i++) { System.out.println(objects[i]); } coll.clear(); System.out.println("集合中内容为:"+coll); System.out.println(coll.isEmpty());
}
|
Iterator接口
java.util.Iterator接口主要用于描述迭代器对象,可以遍历Collection集合中的所有元素。 java.util.Collection接口继承Iterator接口,因此所有实现Collection接口的实现类都可以使用该迭代器对象。
方法声明 |
功能介绍 |
boolean hasNext() |
判断集合中是否有可以迭代/访问的元素 |
E next() |
用于取出一个元素并指向下一个元素 |
void remove() |
用于删除访问到的最后一个元素 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public static void main(String[] args) { Collection c1 = new ArrayList(); c1.add("one"); c1.add(2); c1.add(new Person("zhangfei", 30)); System.out.println("c1 = " + c1); System.out.println("-----------------------------"); Iterator iterator1 = c1.iterator(); System.out.println(iterator1.hasNext()); System.out.println("获取到的元素是:" + iterator1.next()); System.out.println(iterator1.hasNext()); System.out.println("获取到的元素是:" + iterator1.next()); System.out.println(iterator1.hasNext()); System.out.println("获取到的元素是:" + iterator1.next()); System.out.println(iterator1.hasNext()); System.out.println("获取到的元素是:" + iterator1.next()); while(iterator1.hasNext()){ System.out.println("获取到的元素是:" + iterator1.next()); } }
|
遍历集合
1 2 3 4 5 6 7 8 9 10 11
| public static void main(String[] args) { Collection<String> coll = new ArrayList<String>(); coll.add("hd"); coll.add("jc"); coll.add("wyb"); for(String s :coll){ System.out.println(s); } }
|
List集合
基本概念
java.util.List集合是Collection集合的子集合,该集合中允许有重复的元素并且有先后放入次序。
该集合的主要实现类有:ArrayList类、LinkedList类、Stack类、Vector类。
其中ArrayList类的底层是采用动态数组进行数据管理的,支持下标访问,增删元素不方便。
其中LinkedList类的底层是采用双向链表进行数据管理的,访问不方便,增删元素方便。
ArrayList 更适合于随 机访问而LinkedList更适合于插入和删除;在性能要求不是特别苛刻的情形下可以忽略这个差别。
其中Stack类的底层是采用动态数组进行数据管理的,该类主要用于描述一种具有后进先出特征的 数据结构,叫做栈(last in first out LIFO)。
其中Vector类的底层是采用动态数组进行数据管理的,该类与ArrayList类相比属于线程安全的 类,效率比较低,以后开发中基本不用。
常用方法
List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了一些根据元素索引来操作集合的特有方法,如下:
public void add(int index, E element)
: 将指定的元素,添加到该集合中的指定位置上。
public E get(int index)
:返回集合中指定位置的元素。
public E remove(int index)
: 移除列表中指定位置的元素, 返回的是被移除的元素。
public E set(int index, E element)
:用指定元素替换集合中指定位置的元素,返回值的更新前的元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| public static void main(String[] args){ List<String> list = new ArrayList<String>(); list.add("图图"); list.add("小美"); list.add("不高兴"); System.out.println(list); list.add(1,"没头脑"); System.out.println(list); System.out.println("删除索引位置为2的元素"); System.out.println(list.remove(2)); System.out.println(list); list.set(0, "三毛"); System.out.println(list); for(int i = 0;i<list.size();i++){ System.out.println(list.get(i)); } for (String string : list) { System.out.println(string); } }
|
List的子类
ArrayList集合
java.util.ArrayList
集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList
是最常用的集合。
LinkedList集合
java.util.LinkedList
集合数据存储的结构是链表结构。方便元素添加、删除的集合。
常用方法
public void addFirst(E e)
:将指定元素插入此列表的开头。
public void addLast(E e)
:将指定元素添加到此列表的结尾。
public E getFirst()
:返回此列表的第一个元素。
public E getLast()
:返回此列表的最后一个元素。
public E removeFirst()
:移除并返回此列表的第一个元素。
public E removeLast()
:移除并返回此列表的最后一个元素。
public E pop()
:从此列表所表示的堆栈处弹出一个元素。
public void push(E e)
:将元素推入此列表所表示的堆栈。
public boolean isEmpty()
:如果列表不包含元素,则返回true。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static void main(String[] args) { LinkedList<String> link = new LinkedList<String>(); link.addFirst("abc1"); link.addFirst("abc2"); link.addFirst("abc3"); System.out.println(link); System.out.println(link.getFirst()); System.out.println(link.getLast()); System.out.println(link.removeFirst()); System.out.println(link.removeLast()); while (!link.isEmpty()) { System.out.println(link.pop()); } System.out.println(link); }
|
Set接口
java.util.Set
接口和java.util.List
接口一样,同样继承自Collection
接口,它与Collection
接口中的方法基本一致,并没有对Collection
接口进行功能上的扩充,只是比Collection
接口更加严格了。与List
接口不同的是,Set
接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。
Set
集合有多个子类,这里我们介绍其中的java.util.HashSet
、java.util.LinkedHashSet
这两个集合。
HashSet集合
底层数据结构是哈希表
存取无序
不可以存储重复元素
没有索引,不能使用普通for循环遍历
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void main(String[] args) throws Exception { Student stu1=new Student("令狐冲",19); Student stu2=new Student("令狐冲",19); Student stu3=new Student("风清扬",79); Student stu4=new Student("岳不群",49); HashSet<Student> set=new HashSet<Student>(); set.add(stu1); set.add(stu2); set.add(stu3); set.add(stu4); System.out.println(set.contains(stu2)); for(Student stu:set){ System.out.println(stu); } }
|
覆盖Student中的equals和hashCode方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Override public boolean equals(Object obj){ if(obj instanceof Student){ Student stu= (Student) obj; if(stu.age==this.age&&stu.name.equals(this.name)){ return true; } } return false; } @Override public int hashCode(){ return name.hashCode()+age; }
|
for循环遍历后删除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| public static void main(String[] args) { Student stu1=new Student("吴作成",18); Student stu2=new Student("杨志超",19); Student stu3=new Student("商政",21); Student stu4=new Student("商政",21); Student stu5=new Student("靳东升",20); HashSet<Student> set=new HashSet<Student>(); set.add(stu1); set.add(stu2); set.add(stu3); set.add(stu4); set.add(stu5); System.out.println(set); HashSet<Student> setDel=new HashSet<Student>(); for(Student stu:set){ if(stu.name.startsWith("商")){ setDel.add(stu); } } set.removeAll(setDel); System.out.println(set); }
|
LinkedHashSet
我们知道HashSet保证元素唯一,可是元素存放进去是没有顺序的,那么我们要保证有序,怎么办呢?
在HashSet下面有一个子类java.util.LinkedHashSet
,它是链表和哈希表组合的一个数据存储结构。
1 2 3 4 5 6 7 8 9 10 11
| public static void main(String[] args) { Set<String> set = new LinkedHashSet<String>(); set.add("bbb"); set.add("aaa"); set.add("abc"); set.add("bbc"); Iterator<String> it = set.iterator(); while (it.hasNext()){ System.out.println(it.next()); } }
|
TreeSet集合
TreeSet集合概述和特点【应用】
TreeSet集合基本使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Set<String> s1 = new TreeSet<>(); System.out.println("s1 = " + s1);
boolean b1 = s1.add("aa"); System.out.println("b1 = " + b1); System.out.println("s1 = " + s1); b1 = s1.add("cc"); System.out.println("b1 = " + b1); System.out.println("s1 = " + s1); b1 = s1.add("bb"); System.out.println("b1 = " + b1);
System.out.println("s1 = " + s1);
|
排序Comparator和Comparable接口
实现Comparable 接口 并重写方法
1 2 3 4 5 6 7 8
| public class Student implements Comparable<Student>{ @Override public int compareTo(Student stu) { if(this.age>stu.age) return -1; if(this.age<stu.age) return 1; return 0; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void main(String[] args) throws Exception { Student stu1=new Student("令狐冲",19); Student stu2=new Student("令狐冲",19); Student stu3=new Student("风清扬",79); Student stu4=new Student("岳不群",49); TreeSet<Student> set= new TreeSet<Student>(); set.add(stu1); set.add(stu2); set.add(stu3); set.add(stu4); System.out.println(set.contains(stu2)); for(Student stu:set){ System.out.println(stu); } }
|
实现Comparator接口的比较器
1 2 3 4 5 6 7 8
| public class StuComptor implements Comparator<Student> { @Override public int compare(Student stu1, Student stu2) { if(stu1.age>stu2.age)return 1; if(stu1.age<stu2.age)return -1; return 0; } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void main(String[] args) throws Exception { Student stu1=new Student("令狐冲",19); Student stu2=new Student("令狐冲",19); Student stu3=new Student("风清扬",79); Student stu4=new Student("岳不群",49); TreeSet<Student> set= new TreeSet<Student>(new StuComptor()); set.add(stu1); set.add(stu2); set.add(stu3); set.add(stu4); System.out.println(set.contains(stu2)); for(Student stu:set){ System.out.println(stu); } }
|
两种比较方式小结
自然排序: 自定义类实现Comparable接口,重写compareTo方法,根据返回值进行排序
比较器排序: 创建TreeSet对象的时候传递Comparator的实现类对象,重写compare方法,根据返回值进行排序
在使用的时候,默认使用自然排序,当自然排序不满足现在的需求时,必须使用比较器排序
两种方式中关于返回值的规则
- 如果返回值为负数,表示当前存入的元素是较小值,存左边
- 如果返回值为0,表示当前存入的元素跟集合中元素重复了,不存
- 如果返回值为正数,表示当前存入的元素是较大值,存右边
Collections
java.utils.Collections
是集合工具类,用来对集合进行操作。部分方法如下:
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中添加一些元素。
public static void shuffle(List<?> list)
:打乱集合顺序。
public static <T> void sort(List<T> list)
:将集合中元素按照默认规则排序。
public static <T> void sort(List<T> list,Comparator<? super T> )
:将集合中元素按照指定规则排序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<Integer>(); Collections.addAll(list, 5, 222, 1,2); System.out.println(list); Collections.sort(list); System.out.println(list); }
|
泛型
泛型的介绍
常情况下集合中可以存放不同类型的对象,是因为将所有对象都看做Object类型放入的,因此 从集合中取出元素时也是Object类型,为了表达该元素真实的数据类型,则需要强制类型转换, 而强制类型转换可能会引发类型转换异常。
为了避免上述错误的发生,从Java5开始增加泛型机制,也就是在集合名称的右侧使用<数据类型> 的方式来明确要求该集合中可以存放的元素类型,若放入其它类型的元素则编译报错。
泛型只在编译时期有效,在运行时期不区分是什么类型。
定义格式:修饰符 class 类名<类型> {}
1 2 3 4 5
| class ArrayList<E>{ public boolean add(E e){} public E get(int index){} .... }
|
使用在类上的语法
1 2 3 4 5 6 7 8 9
| public class JavaBean<T> { private T t; public T getT() { return t; } public void setT(T t) { this.t = t; } }
|
泛型方法
定义格式:修饰符 <类型> 返回值类型 方法名(类型 变量名) {}
public void/Integer test(T t)
带有泛型方法的类
1 2 3 4 5
| public class JavaObject { public <T> void set(T t){ System.out.println(t); } }
|
1 2 3 4 5
| public static void main(String[] args) { JavaObject j = new JavaObject(); j.set("hd"); j.set(88); }
|
泛型接口
定义格式: 修饰符 interface 接口名<类型> {}
1 2 3
| public interface JavaInterface<T> { void set(T t); }
|
1 2 3 4 5 6
| public class JavaObjectImpl1 implements JavaInterface<Integer>{ @Override public void set(Integer t) { System.out.println(t); } }
|
1 2 3 4 5 6
| public static void main(String[] args) { JavaObjectImpl<String> obj1= new JavaObjectImpl<String>(); obj1.set("hd"); JavaObjectImpl<Integer> obj2= new JavaObjectImpl<Integer>(); obj2.set(88); }
|
类型通配符
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。
通配符高级使用—-受限泛型
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限和下限。
泛型的上限:
泛型的下限:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public static void main(String[] args) { Collection<Integer> list1 = new ArrayList<Integer>(); Collection<String> list2 = new ArrayList<String>(); Collection<Number> list3 = new ArrayList<Number>(); Collection<Object> list4 = new ArrayList<Object>(); getElement(list1); getElement(list2); getElement(list3); getElement(list4); getElement2(list1); getElement2(list2); getElement2(list3); getElement2(list4); }
public static void getElement1(Collection<? extends Number> coll){}
public static void getElement2(Collection<? super Number> coll){}
|
Map集合
Map集合概述
interface Map<K,V> K:键的类型;V:值的类型
Map集合的特点
双列集合,一个键对应一个值
键不可以重复,值可以重复
Map集合的基本功能
方法名 |
说明 |
V put(K key,V value) |
添加元素 |
V remove(Object key) |
根据键删除键值对元素 |
void clear() |
移除所有的键值对元素 |
boolean containsKey(Object key) |
判断集合是否包含指定的键 |
boolean containsValue(Object value) |
判断集合是否包含指定的值 |
boolean isEmpty() |
判断集合是否为空 |
int size() |
集合的长度,也就是集合中键值对的个数 |
遍历方法
方法名 |
说明 |
V get(Object key) |
根据键获取值 |
Set keySet() |
获取所有键的集合 |
Collection values() |
获取所有值的集合 |
Set<Map.Entry<K,V>> entrySet() |
获取所有键值对对象的集合 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| public static void main(String[] args) { Map<String, String> m1 = new HashMap<>(); System.out.println("m1 = " + m1); String str1 = m1.put("1", "one"); System.out.println("原来的value数值为:" + str1); System.out.println("m1 = " + m1); str1 = m1.put("2", "two"); System.out.println("原来的value数值为:" + str1); System.out.println("m1 = " + m1); str1 = m1.put("3", "three"); System.out.println("原来的value数值为:" + str1); System.out.println("m1 = " + m1); str1 = m1.put("1", "eleven"); System.out.println("原来的value数值为:" + str1); System.out.println("m1 = " + m1); System.out.println("----------------"); boolean b1 = m1.containsKey("11"); System.out.println("b1 = " + b1); b1 = m1.containsKey("1"); System.out.println("b1 = " + b1); b1 = m1.containsValue("one"); System.out.println("b1 = " + b1); b1 = m1.containsValue("eleven"); System.out.println("b1 = " + b1); String str2 = m1.get("5"); System.out.println("str2 = " + str2); str2 = m1.get("3"); System.out.println("str2 = " + str2); System.out.println("-------------------------------------"); str2 = m1.remove("1"); System.out.println("被删除的value是:" + str2); System.out.println("m1 = " + m1); System.out.println("---------------------------------------"); Set<String> s1 = m1.keySet(); for (String ts : s1) { System.out.println(ts + "=" + m1.get(ts)); } System.out.println("-----------------------------------"); Collection<String> co = m1.values(); for (String ts : co) { System.out.println("ts = " + ts); } System.out.println("------------------------------------------"); Set<Map.Entry<String, String>> entries = m1.entrySet(); for (Map.Entry<String, String> me : entries) { System.out.println(me); } }
|
HashMap集合
HashMap集合概述和特点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static void main(String[] args) { String str = "abcaba"; HashMap<Character, Integer> map = new HashMap<>(); for (char zimu:str.toCharArray()) { if(map.containsKey(zimu)){ Integer cishu = map.get(zimu); cishu++; map.put(zimu,cishu); }else{ map.put(zimu,1); } } }
|
TreeMap集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| public class Student implements Comparable<Student>{ 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 String toString() { return "Student{"+"name='" + name + '\'' +", age=" + age +'}'; } @Override public int compareTo(Student o) { int result = o.getAge() - this.getAge(); result = result == 0 ? o.getName().compareTo(this.getName()) : result; return result; }s }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class Test1 { public static void main(String[] args) { TreeMap<Student,String> tm = new TreeMap<>(); Student s1 = new Student("hd",88); Student s2 = new Student("jc",99); tm.put(s1,"郑州"); tm.put(s2,"北京"); Set<Map.Entry<Student, String>> entries = tm.entrySet(); for (Map.Entry<Student, String> entry:entries) { Student key = entry.getKey(); String value = entry.getValue(); System.out.println("key:" + key + "value:" + value); } } }
|