Java中的集合Collection和数组具有相同的功能,都是作为存储数据的容器。但是二者也有以下几点不同之处:
1:数组长度固定,集合长度可变;
2:数组能存基本数据类型和引用数据类型,集合只能存引用数据类型,在1.5版本以后,自动装箱与自动解箱也适用于集合中了;
3:数组只能存单一数据类型,集合能存任意引用类型。
Collection的具体分类如下图所示:
其中List和Set的最大区别如下:
1:List中的元素有序,可以重复,判断的依据是equals
2:Set中的元素无序,不可重复,判断的依据是equals和hashcode,具体规则如下:
a:先判断hashcode值,如果不同,则把元素插入到集合中,如果相同在看看equals的值
b:如果equals只也相同,则证明是同一个元素,不能插入到集合中,若equals值不同,则把元素插入到集合中。
在学习具体的集合之前,先来看看几个小知识点:
1:泛型
泛型就是“类/接口<元素类型>”。可以规范元素类型,也可以避免强制类型转换。具体的实例在稍后的例子中体现出来。
2:迭代器Iterator
集合,数组的输出方式有很多,有重写toString()方法,for循环输出,还有一种就是运用迭代器实现更好的输出。
使用时还要注意:
a:要定义在循环外面
b:每个迭代器只能使用一次(如果还要用,则就在定义一个)
c:迭代器的方法中hasNext()不移动指针,始终指向集合中第一个元素的前面
d:迭代器中的next()方法,移动指针,每next一下,跳过一个元素
3:集合均具备的几个基本方法:(具体的使用请看例子)
a:增加:add(Object)及重载
b:删除:remove(index)删除index处的元素、remove(Object)删除Object元素、clear()清空集合
c:修改:set(index,Object)把index处的元素改为Object
d:查找:contains(Object)是否包含Object元素,返回Boolean类型
4:快速输出
for(元素类型 变量名:集合对象/数组对象){//输出语句}
好了,整体的把握我们已经有了,下面我们就进入具体的学习吧:
一:List集合(有序可重)
1:ArrayList,底层是Object数组。具体使用:
package _725; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class MyArrayList { public static void main(String[] args) { List<String> list = new ArrayList<String>(); //增加 list.add("one"); list.add("two"); list.add("three"); list.add("four"); System.out.println(list);//[one, two, three, four] //修改 list.set(1,"five"); System.out.println(list);//[one, five, three, four] //查找 boolean b = list.contains("lisi"); System.out.println(b);//false //删除 list.remove(1);//删除的下标为1(第二个)元素 System.out.println(list);//[one, three, four] list.remove("four");//删除的是four元素 System.out.println(list);//[one, three] //第一种输出 for(int j=0;j<list.size();j++){ System.out.println(list.get(j));//还是按原来J位置上元素的类型输出 } //第二种输出 for(String s:list){ System.out.println(s); } //第三种输出 Iterator<String> it = list.iterator(); while(it.hasNext()){ System.out.println(it.next()); } } }
2:Vector
和ArrayList的的用法基本一致,和ArrayList的几点不同如下:
a:推出时间不一致。Vector在JDK1.0 ArrayList在JDK1.2
b:线程安全。Vector线程安全,ArrayList非线程安全
c:ArrayList效率高。
具体使用和ArrayList差不多,上述程序只需将上面程序中的
public static void main(String[] args) { List<String> list = new ArrayList<String>();
改为:
public static void main(String[] args) { List<String> list = new Vector<String>();
3:LinkedList 底层是双向链表
与Arraylist的不同之处在于:ArrayList多用于查询,而LinkedList多用于频繁的添加。
和ArrayList用法基本一致。将2中的
public static void main(String[] args) { List<String> list = new Vector<String>();
改为:
public static void main(String[] args) { List<String> list = new LinkedList<String>();
二:Set集合(无序不可重)
1:HashSet 底层hash表。具体使用:
package _725; import java.util.HashSet; public class MySet { public static void main(String[] args) { //存取无序,不可重复 HashSet<String> set = new HashSet<String>(); //增加 set.add("one"); set.add("three"); set.add("one"); set.add("two"); set.add("five"); set.add("four"); //输出 for(String s:set){ System.out.print(s+" ");//one two five four three } System.out.println(); //查找 System.out.println(set.contains("five"));//true //删除 set.remove("five"); System.out.println(set);//[one, two, four, three] } }
2:TreeSet 底层是二叉树
特点:有序,自动排序。去重。
比较可以有两种方式:
a:类 implements Compareable接口,重写compareTo()方法。(对应下面例子中的1)
b:更灵活的方式,让TreeList本身具有可比较性,在构造方法中传一个Comparator对象,重写compare方法。(对应下面例子中的2,3,4)
几个“比较”的方法:
1:在实体类中重写compareTo接口的方法
public class Person implements Comparable<Person>{ private String name; private int age; @Override public int compareTo(Person o) { // TODO Auto-generated method stub //return 0; //return this.age-o.age; //return o.age-this.age; //return this.name.compareTo(o.name); return o.name.compareTo(this.name); }
测试类及运行结果为:
public class TestPersonTreeSet { public static void main(String[] args) { Set<Person> set = new TreeSet<Person>(); Person p1 = new Person("zhangsan", 20); Person p2 = new Person("lisi", 21); Person p3 = new Person("zhangsan", 20); Person p4 = new Person("wangwu", 22); set.add(p1); set.add(p2); set.add(p3); set.add(p4); // 注意在Person类中实现了Compareable接口及其方法,所以才可以存得进去 //如果不改变原来付接口中得方法,只能存进去一个 Iterator<Person> it = set.iterator(); while(it.hasNext()){ System.out.println(it.next()); /* * Person [name=zhangsan, age=20] * Person [name=wangwu, age=22] * Person [name=lisi, age=21] */ } } }
2:静态内部类。这时应把实体类中“implements Comparable<Person>”删除掉。在具体的测试类中的main方法里有:
public class TtestPersonByIterator { public static void main(String[] args) { // 此时要把Person类中的implements注释掉 实现灵活排序 Set<Person> set = new TreeSet<Person>(new PersonCom());// 传过来比较器对象 Person p1 = new Person("zhangsan", 20); Person p2 = new Person("lisi", 21); set.add(p1); set.add(p2); Iterator<Person> it = set.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } // 静态内部类,作为用比较器实现排序的类,要实现Comparator接口 static class PersonCom implements Comparator<Person> { @Override public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } } }
3:单提出一个类完成功能。这时应把实体类中“implements Comparable<Person>”删除掉。在具体的测试类中的main方法里有:
public class TestPersonByIterarot2 { public static void main(String[] args) { //此时要把Person类中的implements注释掉 实现灵活排序 Set<Person> set = new TreeSet<Person>(new PersonCom());// 传过来比较器对象 Person p1 = new Person("zhangsan", 20); Person p2 = new Person("lisi", 21); set.add(p1); set.add(p2); Iterator<Person> it = set.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } } // 单提出来一个类 class PersonCom implements Comparator<Person> { @Override public int compare(Person o1, Person o2) { System.out.println(o1.getName() + ":" + o2.getName()); return o1.getAge() - o2.getAge(); } }
4:匿名内部类。 这时应把实体类中“implements Comparable<Person>”删除掉。在具体的测试类中的main方法里有:
public class TestPersonByIterator3 { public static void main(String[] args) { // 此时要把Person类中的implements注释掉 实现灵活排序 Set<Person> set = new TreeSet<Person>(new Comparator<Person>() { // 匿名内部类的使用 @Override public int compare(Person o1, Person o2) { return o1.getAge() - o2.getAge(); } });// 传过来比较器对象 Person p1 = new Person("zhangsan", 20); Person p2 = new Person("lisi", 21); set.add(p1); set.add(p2); Iterator<Person> it = set.iterator(); while (it.hasNext()) { System.out.println(it.next()); } } }
未完,待续。。。