Java集合可分为Collection和Map两种体系
- Collection接口:Set 元素无序(不等于随机性,真正的无序性,指的是元素在底层存储的位置是无序的)、不可重复的集合;List 元素有序,可重复的集合
- Map接口:具有映射关系"Key-Value对"的集合
一、List
ArrayList和LinkedList的大致区别如下:
- ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构
- 对于随机访问get和set,ArrayList优于LinkedList,因为LinkedList要移动指针
- 对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据
- ArrayList没有实现Queue队列接口,LinkedList实现了Queue接口
创建Person实体类
package com.yyx.test; /** * 实体类 人 * * @author yyx 2018年6月11日 */ public class Person { private String perName; private int perAge; public Person() { super(); } public Person(String perName, int perAge) { super(); this.perName = perName; this.perAge = perAge; } public String getPerName() { return perName; } public void setPerName(String perName) { this.perName = perName; } public int getPerAge() { return perAge; } public void setPerAge(int perAge) { this.perAge = perAge; } @Override public String toString() { return "Person [perName=" + perName + ", perAge=" + perAge + "]"; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (this.perAge != other.perAge) return false; if (this.perName == null) { if (other.perName != null) return false; } else if (!this.perName.equals(other.perName)) return false; return true; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + this.perAge; result = prime * result + ((this.perName == null) ? 0 : this.perName.hashCode()); return result; } }
1.ArrayList(主要实现类)
package com.yyx.test; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Pratice { public static void main(String[] args) { List<Person> listPerson = new ArrayList<Person>(); Person perOne = new Person("张三", 22); Person perTwo = new Person("李四", 21); Person perThree = new Person("王五", 25); listPerson.add(perOne); listPerson.add(perTwo); listPerson.add(perThree); //遍历方法一 for (int i = 0; i < listPerson.size(); i++) { System.out.println(listPerson.get(i).toString()); } listPerson.remove(perOne); System.out.println(); //遍历方法二 for (Person person : listPerson) { System.out.println(person.toString()); } listPerson.remove(1); System.out.println(); //遍历方法三 Iterator<Person> iterator=listPerson.iterator(); while (iterator.hasNext()) { Person person =iterator.next(); System.out.println(person.toString()); } } }
2.LinkedList
package com.yyx.test; import java.util.Iterator; import java.util.LinkedList; /** * LinkedList的详细方法参考Api帮助文档 * @author yyx 2018年6月11日 */ public class Pratice { public static void main(String[] args) { LinkedList<Person> listPerson = new LinkedList<Person>(); Person perOne = new Person("张三", 22); Person perTwo = new Person("李四", 21); listPerson.add(perOne); listPerson.add(perTwo); for (Person person : listPerson) { System.out.println(person.toString()); } System.out.println(); Person perThree = new Person("王五", 25); listPerson.addFirst(perThree); for (Person person : listPerson) { System.out.println(person.toString()); } System.out.println(); listPerson.removeLast(); //遍历方法三 Iterator<Person> iterator=listPerson.iterator(); while (iterator.hasNext()) { Person person =iterator.next(); System.out.println(person.toString()); } } }
3.Vector
Vector是线程安全的,影响效率,故此Vector的效率低于ArrayList,Vector类可以实现可增长的对象数组
Vector与ArrayList的比较
- Vector是线程安全的集合类,ArrayList并不是线程安全的类。Vector类对集合的元素操作时都加了synchronized,保证线程安全。
- Vector与ArrayList本质上都是一个Object[] 数组,ArrayList提供了size属性,Vector提供了elementCount属性,他们的作用是记录集合内有效元素的个数。与我们平常调用的arrayList.size()和vector.size()一样返回的集合内有效元素的个数。
- Vector与ArrayList的扩容并不一样,Vector默认扩容是增长一倍的容量,Arraylist是增长50%的容量。
- Vector与ArrayList的remove,add(index,obj)方法都会导致内部数组进行数据拷贝的操作,这样在大数据量时,可能会影响效率。
- Vector与ArrayList的add(obj)方法,如果新增的有效元素个数超过数组本身的长度,都会导致数组进行扩容
二、Set
Set:存储的元素是无序的,不可重复的!
- 1.无序性:无序性!= 随机性。真正的无序性,指的是元素在底层存储的位置是无序的
2.不可重复性:当向Set中添加进相同的元素的时候,后面的这个不能添加进去
1.HashSet (主要实现类)
package com.yyx.test; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class Pratice { public static void main(String[] args) { /** * 要求添加进Set中的元素所在的类,一定要重写equals()和hashCode()方法。 * 进而保证Set中元素的不可重复性 */ Set<Person> set = new HashSet<Person>(); Person p1 = new Person("GG", 23); Person p2 = new Person("GG", 23); Person p3 = new Person("FF", 22); set.add(p1); set.add(p2); set.add(p3); Iterator<Person> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } System.out.println(p1.equals(p2)); System.out.println(p1.hashCode()); System.out.println(p2.hashCode()); System.out.println(p3.hashCode()); } }
2.TreeSet
- 向TreeSet中添加的元素必须是同一个类的
- 可以按照添加进集合中的元素的指定的顺序遍历。像String,包装类等默认按照从小到大的顺序遍历
- 当向TreeSet中添加自定义类的对象时,有两种排序方法:①自然排序②定制排序
- 自然排序:要求自定义类实现java.lang.Comparable接口并重写其compareTo(Object obj)的抽象方法在此方法中,指明按照自定义类的哪个属性进行排序
- 向TreeSet中添加元素时,首先按照compareTo()进行比较,一旦返回0,虽然仅是两个对象的此属性值相同,但是程序会认为这两个对象是相同的,进而后一个对象就不能添加进来
注意:compareTo()与hashCode()以及equals()三者保持一致!
package com.yyx.test; import java.util.Iterator; import java.util.Set; import java.util.TreeSet; /** * * @author yyx 2018年6月11日 */ public class Pratice { public static void main(String[] args) { Set<Person> set = new TreeSet<Person>(); set.add(new Person("CC", 23)); set.add(new Person("MM", 21)); set.add(new Person("GG", 25)); set.add(new Person("JJ", 24)); set.add(new Person("KK", 20)); set.add(new Person("DD", 20)); /** * 当Person类没有实现Comparable接口时,当向TreeSet中添加Person对象时, * 报ClassCastException */ Iterator<Person> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } } }
TreeSet的定制排序: 见下面的步骤 compare()与hashCode()以及equals()三者保持一致!
package com.yyx.test; /** * * @author yyx 2018年6月12日 */ public class Customer { private String name; private Integer id; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public Customer(String name, Integer id) { super(); this.name = name; this.id = id; } public Customer() { super(); } @Override public String toString() { return "Customer [name=" + name + ", id=" + id + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((id == null) ? 0 : id.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Customer other = (Customer) obj; if (id == null) { if (other.id != null) return false; } else if (!id.equals(other.id)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
package com.yyx.test; import java.util.Comparator; import java.util.TreeSet; /** * * @author yyx 2018年6月11日 */ public class Pratice { public static void main(String[] args) { // 1.创建一个实现了Comparator接口的类对象 Comparator com = new Comparator() { // 向TreeSet中添加Customer类的对象,在此compare()方法中,指明是按照Customer // 的哪个属性排序的。 @Override public int compare(Object o1, Object o2) { if (o1 instanceof Customer && o2 instanceof Customer) { Customer c1 = (Customer) o1; Customer c2 = (Customer) o2; int i = c1.getId().compareTo(c2.getId()); if (i == 0) { return c1.getName().compareTo(c2.getName()); } return i; } return 0; } }; // 2.将此对象作为形参传递给TreeSet的构造器中 TreeSet<Customer> set = new TreeSet<Customer>(com); // 3.向TreeSet中添加Comparator接口中的compare方法中涉及的类的对象。 set.add(new Customer("AA", 1003)); set.add(new Customer("BB", 1002)); set.add(new Customer("GG", 1004)); set.add(new Customer("CC", 1001)); set.add(new Customer("DD", 1001)); for (Object str : set) { System.out.println(str); } } }
3.LinkedHashSet
- LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的
- LinkedHashSet 是 HashSet 的子类
- LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能
package com.yyx.test; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; /** * * @author yyx 2018年6月11日 */ public class Pratice { public static void main(String[] args) { Set<Person> set = new LinkedHashSet<Person>(); Person p1 = new Person("GG", 23); Person p2 = new Person("GG", 23); Person p3 = new Person("FF", 22); Person p4 = new Person("EE", 22); set.add(p3); set.add(p1); set.add(p2); set.add(p4); Iterator<Person> iterator = set.iterator(); while (iterator.hasNext()) { System.out.println(iterator.next()); } System.out.println(p1.equals(p2)); System.out.println(p1.hashCode()); System.out.println(p2.hashCode()); System.out.println(p3.hashCode()); } }
三、Map
- Map与Collection并列存在。用于保存具有映射关系的数据:Key-Value
- Map 中的 key 和 value 都可以是任何引用类型的数据
- Map 中的 key 用Set来存放,不允许重复,即同一个,常用String类作为Map的“键”
- key 和 value 之间存在单向一对一关系,即通过指定的 key 总能找到唯一的、确定的 value
HashMap(常用类)