学习笔记20
Collection接口:
*常用的实现类:
Set接口实例存储的是无序的,不重复的数据。List接口实例存储的是有序的,可以重复的元素。
1.List接口:存入的元素有序,元素不唯一。
1.1 ArrayList:线程不安全。底层是数组,查找快,增删慢。
public static void main(String [] ards){
ArrayList list = new ArrayList();
list.add(3); //默认在尾部加入新的元素
list.add(0, "汉字"); //指定位置添加新元素
list.add(0, '家');
list.add(0, 8);
list.add(5);
list.add(7);
System.out.println("\n数组长度:" + list.size()); //数组长度
//ArrayList常用方法
Object arr = list.get(0); //获取指定位置的元素,元素返回值是Object类型
System.out.println("0位置元素:"+arr);
Object obj=list.set(1, 3); //修改指定位置的元素值,返回值是原来该位置上的元素
System.out.println("将1位置元素修改为3的返回值:"+obj);
System.out.println("将1位置元素修改为3后打印:"+list); //toString打印数组
// 返回值为-1说明该元素不存在
System.out.println("元素3第一次出现的位置:"+list.indexOf(3)); //得到指定元素第一次出现的位置索引
System.out.println("判断集合中是否存在元素‘汉字’:"+list.contains("汉字")); //判断数组中是否存在某元素*/
System.out.println("是否成功删除元素3:"+list.remove(new Integer(3))); //判断是否成功删除某元素,返回true,false
//当删除的元素是整型的时候必须放到包装类中,否则则默认删除指定位置的元素
System.out.println("是否成功删除元素1.2:"+list.remove(1.2));
System.out.println("删除成功时返回索引为0的元素:"+list.remove(0)); //删除指定位置的元素,并返回该位置的元素值
System.out.println("删除后数组长度:" + list.size());
list.clear();
System.out.println("数组是否为空:" + list.isEmpty());
System.out.println("清空数组后长度:" + list.size());
}
1.2 LinkedList:线程不安全。底层是链表,查找慢,增删快。
public static void main(String[] args) {
LinkedList list=new LinkedList();
list.add("111");
list.addFirst("好");
list.addFirst("ff");
list.addFirst(23);
list.addLast("111");
list.addLast(0);
System.out.println(list);
System.out.println("list.contains(\"111\"):"+list.contains("111"));
System.out.println("list.element():"+list.element());
System.out.println("list.get(0):"+list.get(0));
System.out.println("list.getFirst():"+list.getFirst());
System.out.println("list.getLast():"+list.getLast());
//元素不存在返回-1
System.out.println("list.indexOf(111):"+list.indexOf("111"));
System.out.println("list.lastIndexOf(\"111\"):"+list.lastIndexOf("111"));
//返回删除的第一个元素
System.out.println("list.remove():"+list.remove());
System.out.println(list);
//删除指定位置的元素,并返回该元素
System.out.println("list.remove(0):"+list.remove(0));
System.out.println(list);
//删除指定元素,不存在返回false
System.out.println("list.remove(new Integer(0)):"+list.remove(new Integer(0)));
System.out.println(list);
//删除第一个位置的元素,并返回该元素
System.out.println("list.removeFirst():"+list.removeFirst());
System.out.println(list);
}
- stack(栈):后进先出(LIFO)的容器
- queue(队列):先进先出(FIFO)的容器。
2.Set接口:加入Set的每个元素是唯一的。
2.1 HashSet:为优化查询速度而设计的Set。要放进HashSet里面的自定义类还要重写hashCode(),equals()方法.
自定义类Student没有重写hashCode(),equals()方法时:
public class Student {
private int no;
private String name;
public Student(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public void setNo(int no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
}
public static void main(String[] args) {
HashSet<Student>hashSet=new HashSet<>();
hashSet.add(new Student(1001,"Jim"));
hashSet.add(new Student(1002,"Jom"));
hashSet.add(new Student(1002,"Jom"));
System.out.println(hashSet);
}
输出结果如下:
总结:由以上输出可以看到在向HashSet中添加数据时,并没有达到数据唯一性要求,可以知道在使用自定义类时必须重写hashCode()、equals()方法判断元素唯一性。(在添加基本数据类型的数据时因为各数据类型的包装类已经重写了这两个方法,所以在这里用引用数据类型来说明)
public class Student {
private int no;
private String name;
public Student(int no, String name) {
this.no = no;
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
if (no != student.no) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = no;
result = 31 * result + (name != null ? name.hashCode() : 0);
return result;
}
}
2.2 TreeSet:是一个有序的Set,其底层是一棵树。所以是有序序列。
//Student类用上面没有重写hashCode()、equals()方法的类。
public static void main(String[] args) {
TreeSet<Student> treeSet=new TreeSet<>();
treeSet.add(new Student(1002,"Jom"));
treeSet.add(new Student(1002,"Jom"));
System.out.println(treeSet);
}
输出结果:
注::在向TreeSet中添加数据时,使用自定义类时不须重写hashCode()、equals()方法,但是必须要实现Comparable或Comparator接口。
public class Student implements Comparable{
private int no;
private String name;
public Student(int no, String name) {
this.no = no;
this.name = name;
}
public int getNo() {
return no;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Student{" +
"no=" + no +
", name='" + name + '\'' +
'}';
}
@Override
public int compareTo(Object o) {
if(((Student)o).getName().equals(name)&&((Student)o).getNo()==no){
return 0;
}else{
return 1;
}
}
}
再次运行程序后输出结果:
- LinkedHashSet:在内部使用链表,既有HashSet的查询速度,又能保证元素被加进去的顺序。用Iterator遍历Set的时候是按插入顺序进行访问的。