集合按照其存储结构可以分为两大类,单列集合Collection和双列集合Map:
1. 单列集合:Collection:
子接口:List 、Set。
List:有索引,可存储重复的数据,存取有序(即怎么存、怎么取)。
Set:没有索引,不可存储重复的数据,存取无序。
Collection常用方法:
add、addAll、remove、removeAll、contains、containsAll、size、clear、isEmpty。
//泛型,可以约束集合存储数据的类型。 Collectionc1 = new ArrayList<>(); //add,添加元素 c1.add("a"); c1.add("b"); c1.add("c"); System.out.println(c1); Collection c2 = new ArrayList<>(); c2.add("e"); //将指定集合所有元素添加到当前集合。 c1.addAll(c2); System.out.println(c1); //删除指定元素 System.out.println(c1.remove("a")); System.out.println(c1); //判断集合是否包含指定元素 System.out.println(c1.contains("c")); //判断集合中是否包含指定集合所有元素 System.out.println(c1.containsAll(c2)); //集合的长度 System.out.println(c1.size()); //将指定集合中所有元素从当前集合中删除 System.out.println(c1.removeAll(c2)); System.out.println(c1); //清空集合 c1.clear(); System.out.println(c1); //判断集合是否为空 System.out.println(c1.isEmpty());
List:
List接口继承了Collection接口中的所有方法,还增加了一些索引操作集合的特有方法。
Listlist = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.add(0,"c");//向指定索引添加数据,若索引不存在,会有异常 System.out.println(list); List list2 = new ArrayList<>(); list2.add("d"); list.addAll(1, list2);//将指定集合添加到当前集合指定索引位置。 System.out.println(list); System.out.println(list.get(1));//获取指定索引元素 System.out.println(list.remove(0));//根据索引删除元素,返回被删除的元素 System.out.println(list); System.out.println(list.set(0,"ff"));//返回被修改的元素 System.out.println(list); System.out.println(list.indexOf("a"));//元素第一次出现位置 System.out.println(list.lastIndexOf("c"));//元素最后出现的位置 System.out.println(list); List list3= list.subList(1,2);//获取指定索引范围元素.返回新的集合 System.out.println(list3);
ArrayList:
Arraylist大部分方法有父类Collection和List继承过来,add、get方法实现存取。
ArrayList特点:
允许插入重复数据。
插入的元素是有序的。
动态扩容。
非线程安全,异步。
基于动态数组的数据结构。
擅长随机访问
使用场景:
底层是数组结构实现的,数组有索引、查询速度比较快、增删比较慢。使用场景:如果大量的数据经常做查询的操作、优先使用ArrayList。
LinkedList:
ArrayList在查询时速度快,但元素增删慢,而LinkedList克服了这种局限性。LinkedList内部维护了一个双向循环链表,链表中每一个元素都用引用的方式记住前一个元素与后一个元素(即与前后元素形成双向引用),当插入、删除元素时,只需要修改这种引用关系即可。所以LinkedList对集合的增删有很高的效率,而在做查询操作没有ArrayList快,可根据场景合理使用不同的方法。
LinkedListlink = new LinkedList<>(); link.add("a"); link.add("b"); link.add("c"); link.add("d"); System.out.println(link); link.addFirst("e");//添加元素到开头 System.out.println(link); link.addLast("f");//添加数据到末尾 System.out.println(link); System.out.println(link.getFirst());//获取第一个元素 System.out.println(link.getLast());//获取最后一个元素 link.removeFirst();//删除第一个元素 link.removeLast();//删除最后一个元素 System.out.println(link);
Iterator:
主要用于遍历集合中的所有元素,也称迭代器(而Collection、Map主要用于存储)。
ArrayListlist = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.add("e"); Iterator it = list.iterator(); //不能在迭代时删除list元素,否则会引发并发异常,可通过迭代器对象操作 while (it.hasNext()){ String str = it.next(); if ("b".equals(str)){ it.remove(); } }
foreach循环:
比for循环写法更加简洁,foreach也称增强for循环,可用于遍历数组或集合。
ArrayListlist = new ArrayList<>(); list.add("a"); list.add("b"); list.add("c"); list.add("d"); list.add("e"); for (String str : list) { System.out.println(str); } int[] arr ={1, 2, 3, 4, 5}; for (int i : arr) { System.out.println(i); }
Set集合:
Set和List都继承自Collection接口,与Collection方法基本一致,并没有进行扩充,但是比Collection更加严格,Set中的元素时无序的并且不重复(List是有序的、可重复的)。
Set的两个实现类:HashSet和TreeSet。
HashSet根据哈希值确当元素所在集合中的存储位置,具有良好的存取性能。
TreeSet以二叉树的方式存储元素,它可以实现对集合中的元素进行排序。
HashSet:
//没有索引、无序、不能重复(HashSet子类LinkedHashSet可以保证存取顺序)。 //根据对象哈希值计算存储位置。 //判断当前位置是否有数据,没有数据:直接存储,有数据:属性值相同不存储(属性值不相同以链表结构存储) HashSeths = new HashSet<>(); hs.add("a"); hs.add("e"); hs.add("c"); hs.add("d"); hs.add("b"); hs.add("e"); for (String h : hs) { System.out.println(h); }
存储自定义对象时需要重写hashCode和equals、否则将会存储重复的对象。
案例:
学生类:
class Student {
String name;
int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
//重写equals
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
//重写hashCode
@Override
public int hashCode() {
return Objects.hash(name, age);
}
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
}
调用:
HashSeths = new HashSet<>(); //LinkedHashSet hs = new LinkedHashSet<>();//可保证存取顺序 Student stu1 = new Student("张三",21); Student stu2 = new Student("张三",21); Student stu3 = new Student("李四",22); Student stu4 = new Student("王五",23); hs.add(stu1); hs.add(stu2); hs.add(stu3); hs.add(stu4); for (Student h : hs) { System.out.println(h); }
TreeSet:
可以对集合中的元素进行排序。
基本使用:
TreeSetts = new TreeSet<>(); ts.add(4); ts.add(2); ts.add(3); ts.add(1); for (Integer t : ts) { System.out.println(t); }
存储自定义对象:
排序方式1:自然排序,自定义的类必须实现Comparable接口,并重写排序条件(不重写则可能会丢失部分数据)。
自定义类:
//实现Comparable class Student implements Comparable{ String name; int age; //省略set、get和构造方法...... @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(name, age); } //重写compareTo方法 // 编写排序规则 //返回值:负数(向左存),0(不存储),整数(向右存)。 @Override public int compareTo(Student o) { //按年龄升序,this在后则按年龄降序 int result = this.age - o.age; //次要条件(避免因为年龄相同对象丢失),如果年龄相同,按姓名排序 if (result == 0){ result = this.name.compareTo(o.name); } return result; } }
使用:
TreeSetts = new TreeSet<>(); Student stu1 = new Student("a1",21); Student stu2 = new Student("a3",24); Student stu3 = new Student("a2",22); Student stu4 = new Student("a0",22); ts.add(stu1); ts.add(stu2); ts.add(stu3); ts.add(stu4); for (Student t : ts) { System.out.println(t); }
比较器方式排序:
//匿名内部类方式传对象,重写compare方法 TreeSet2. 双列集合:ts = new TreeSet<>(new Comparator (){ @Override public int compare(Integer o1, Integer o2) {//o1要存的数据,o2已经存进去的数据 //o2 - o1降序,o1 - o2升序 int result = o1 - o2; return result; } }); ts.add(4); ts.add(2); ts.add(3); ts.add(1); for (Integer t : ts) { System.out.println(t); }
Map:
常用实现类:Hashtable 、HashMap、TreeMap。
Hashtable :最早期的双列集合,目前少用,但是子类Properties一直沿用。
HashMap : 基于哈希表的 Map 接口的实现。
TreeMap:不仅实现了Map接口,还实现了java.util.SortMap接口。
HashMap是非线程安全的,也就是说在多线程的环境下,可能会存在问题,而Hashtable是线程安全的。
Map接口是一种双列集合,每个元素都包含一个Key、value值(key的值不能重复、value的值可以重复),键值之间存在映射关系,访问元素时,只要指定了key,就能找到value。
常用实现类:Hashtable 、HashMap 、TreeMap、Properties、LinkedHashMap。
Map接口常用方法:
常用方法及遍历集合方式:
//泛型,Map是接口不能new,new实现类。 Mapm = new HashMap<>(); m.put("k1","a");//添加数据 m.put("k2","a"); m.put("k3","b"); m.put("k3","c"); m.put("k4","e"); System.out.println(m); System.out.println(m.get("k2"));//获取值 String rm = m.remove("k4");//删除数据,返回被删除的值 System.out.println(rm); System.out.println(m); System.out.println(m.size());//获取集合长度 System.out.println(m.containsKey("k2"));//判断是否包含指定的key System.out.println(m.containsKey("k5"));//判断是否包含指定的key System.out.println(m.containsValue("a"));//判断是否存在指定的值 System.out.println(m.containsValue("f"));//判断是否存在指定的值 System.out.println(m); Collection c1= m.values();//获取所有的值,保存到单列集合 System.out.println(c1); Collection c2= m.keySet();//获取所有的key值,保存到单列集合 System.out.println(c2); //遍历集合1 Set ks= m.keySet();//获取所有的key值,保存到单列集合Set for (String s : ks) { System.out.println(m.get(s)); } //遍历集合2 Set > entries = m.entrySet();//获取键值对对象,保存到Set集合。 for (Map.Entry entry : entries) { String key = entry.getKey(); String value = entry.getValue(); System.out.println("key:"+key+" value:"+value); } m.clear();//清空集合 System.out.println(m);
HashMap集合:
map集合中的一个实现类,比较常用。
没有重复键,键值无序。
没有提供特有方法,特点很多与Map一样。
使用子类LinkedHashMap保证存储顺序,其他特点与Map接口一样
//通过泛型指定键值类型 //HashMaphm = new HashMap<>(); //使用LinkedHashMap可以保证存储顺序,其他特点与Map接口一样 LinkedHashMap hm = new LinkedHashMap<>(); hm.put("k1","a");//添加数据 hm.put("k2","a"); hm.put("k3","b"); hm.put("k3","c"); hm.put("k4","e"); System.out.println(hm); //遍历集合 Set ks = hm.keySet(); for (String k : ks) { System.out.println(hm.get(k)); } //同样可以用Map的entrySet()方式遍历
TreeMap集合
特点:HashMap键值无序、不可重复,TreeMap可对集合中的元素进行排序。
使用:
TreeMaptm = new TreeMap<>(new Comparator () { @Override public int compare(Integer o1, Integer o2) { int result = o2 - o1; return result; } }); tm.put(1,"b"); tm.put(3,"c"); tm.put(2,"a"); tm.put(4,"d"); System.out.println(tm);
Properties
Map中的一个集合Hashtable(早期的使用,使用与HashMap类似,但是HashTable是线程安全的,HashTable存取速度很慢,基本与HashMap取代),但是他的子类Properties至今仍很常用(例如IO流读取配置文件等)。
可以如下使用(但是实际应用场景一般用于IO流的配置文件操作)。
Properties prpo = new Properties();
prpo.put("username","username1");
prpo.put("password","password1");
Set



