zoukankan      html  css  js  c++  java
  • Java 面向对象(十一)

    常用类之集合

    集合:就是用来存放数据的一个容器。

    数组和集合的区别

    (1)数组能存基本数据类型和引用类型;集合当中只能存放引用数据类型,直接放基本数据类型,也会自动帮你装箱(把基本数据类型转成对象),集合当中只能存放对象。

    (2)数组长度是固定,不能再去增长;集合长度是可以改变,根据元素的增长而增加。

    什么时候使用数组,什么时候使用集合类。

    如果元素个数是固定,推荐使用数组;如果元素不是固定,推荐使用集合。

    集合体系

    这里介绍集合体系的一部分。

    Collection 接口

    常用方法

    /* 
     * 向 collection 中添加指定的元素,
     * 如果添加成功返回 true,没有添加返回 false。
     * 确保此 collection 包含指定的元素。
     */
    boolean add(E e) 
    
    
    /*
     * 将指定 collection 中的所有元素都添加到此 collection 中
     * 如果此 collection 由于调用而发生更改,则返回 true。 否则返回 false。
     */
    boolean addAll(Collection<? extends E> c) 
    
    
    // 移除此 collection 中的所有元素
    void clear() 
    
    
    // 如果此 collection 包含指定的元素,则返回 true。否则返回 false。
    boolean contains(Object o) 
    
    
    // 如果此 collection 包含指定 collection 中的所有元素,则返回 true。否则返回 false。
    boolean containsAll(Collection<?> c) 
    
    
    /*
     * 比较此 collection 与指定对象是否相等。
     * 如果所定义的两个列表以相同的顺序包含相同的元素,则返回 true。
     */
    boolean equals(Object o) 
    
        
    // 如果此 collection 不包含元素,则返回 true。
    boolean isEmpty() 
    
    
    // 返回在此 collection 的元素上进行迭代的迭代器。
    Iterator<E> iterator() 
    
    
    // 从此 collection 中移除指定元素的单个实例,如果存在的话,移除成功,则返回 true。
    boolean remove(Object o) 
    
    
    /*
     * 移除此 collection 中,此 collection和指定 collection的交集
     * 如果此 collection 由于调用而发生更改,则返回 true
     */
    boolean removeAll(Collection<?> c) 
    
    
    /*
     * 把此 collection和指定 collection的交集赋值给调用者
     * 如果此 collection 由于调用而发生更改,则返回 true
     */
    boolean retainAll(Collection<?> c) 
    
    
    // 返回此 collection 中的元素数。
    int size() 
    
    
    // 返回包含此 collection 中所有元素的数组
    Object[] toArray() 
    
    
    // 返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。
    <T> T[] toArray(T[] a) 
    

    管理集合元素:

    增:add(E e) 
    
    删:remove(Object o) 
    
    改:Collection中没有定义
    
    清空:clear() 
    

    查:

    个数:size()
    
    判包含:contains(Object o)
    
    判空:isEmpty() 
    
    查找定位某个元素:Collection中没有定义
    

    e.g.

    public static void main(String[] args) {
    	Collection c = new ArrayList();
    	// 会自动帮你装箱(把基本数据类型转成对象)
    	c.add(10); 
    	c.add(true);
    }
    

    反编译后:

    public static void main(String args[])
    {
    	Collection c = new ArrayList();
    	c.add(Integer.valueOf(10));
    	c.add(Boolean.valueOf(true));
    }
    

    e.g. Collection 遍历

    public static void main(String[] args) {
    	Collection c = new ArrayList();
    	c.add(new Student("zs"));
    	c.add(new Student("ls"));
    	c.add(new Student("ww"));
    
    	// (1)转成数组,通过数组遍历
    	Object[] array = c.toArray(); // 自动把数组当中所有元素向上转型
    	for (int i = 0; i < array.length; i++) {
    		if (array[i] instanceof Student) { // 向下转型有风险
    			Student s = (Student) array[i]; // 向下转型(转回原来存放的类型)
    			System.out.println(s.name);
    		}
    	}
    
    	System.out.println("-----分割线------");
    
    	// (2)迭代器遍历(推荐)
    	Iterator it = c.iterator(); // 放到Iterator内容会自动类型提升为 Object
    
    	// 1.判断有没有元素可以迭代,如果仍有,则返回 true。
    	while (it.hasNext()) {
    		// 2. 返回游标的下一个元素,游标后移一位
    		Object next = it.next();
    		if (next instanceof Student) {
    			Student s = (Student) next;
    			System.out.println(s.name);
    		}
    	}
    }
    

    List 接口

    常用方法

    由 Collection 接口继承来的不再说明,见Collection 接口的常用方法

    // 在列表的指定位置插入指定元素 
    void add(int index, E element) 
    
    
    /*
     * 将指定 collection 中的所有元素都插入到列表中的指定位置 
     * 如果此 collection 由于调用而发生更改,则返回 true。 否则返回 false。
     */
    boolean addAll(int index, Collection<? extends E> c) 
    
    
    // 移除列表中指定位置的元素,返回从列表中移除的元素
    E remove(int index) 
    
    
    // 返回列表中指定位置的元素
    E get(int index) 
    
    
    // 用指定元素替换列表中指定位置的元素,返回被替换的元素
    E set(int index, E element) 
    
    
    // 返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1
    int indexOf(Object o) 
    
    
    // 返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1
    int lastIndexOf(Object o)
    
    
    // 返回此列表元素的列表迭代器(按适当顺序)
    ListIterator<E> listIterator()
    
    
    // 返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始
    ListIterator<E> listIterator(int index)
    
    
    // 返回列表中指定的 [fromIndex, toIndex) 之间的部分视图。
    List<E> subList(int fromIndex, int toIndex)
    
    
    // 使用随附的 Comparator排序此列表来比较元素。
    default void sort(Comparator<? super E> c) 
    

    管理集合元素:

    增:add(E e) ;  add(int index, E element) 
    
    删:remove(Object o) ;  remove(int index) 
    
    改:set(int index, E element) 
    
    清空:clear() 
    
    排序:sort(Comparator<? super E> c) 
    
    子集合:subList(int fromIndex, int toIndex)
    

    查:

    个数:size()
    
    判包含:contains(Object o)
    
    判空:isEmpty() 
    
    查找定位某个元素:indexOf(Object o) ; lastIndexOf(Object o)  ;  get(int index) 
    

    e.g.

    现在有个需求,遍历集合,如果集合中的元素等于某个值,删除这个元素。

    List list = new  ArrayList();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    
    // 遍历集合
    Iterator it = list.iterator();
    
    while(it.hasNext()) {
    	// 取出对应的元素
    	String str = (String)it.next();
    	// 判断该 元素是否等于 2
    	if(str.equals("2")) {
    		// 等于 2 就把2给集合当中删除
    		list.remove("2");
    	}
    }
    System.out.println(list);
    

    以上代码会报 java.util.ConcurrentModificationException 并发修改异常

    在迭代集合的过程当中,是不允许直接修改集合结构。

    看下源码:

    修改后:

    List list = new  ArrayList();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    
    Iterator it = list.iterator();
    
    while(it.hasNext()) {
    	String str = (String)it.next();
    	if(str.equals("2")) {
    		it.remove(); // 删除当前正在迭代集合的元素(正在遍历的元素 next的结果)
    	}
    }
    System.out.println(list);
    

    原理:

    e.g. List特有的迭代器

    现在换了一个需求,遍历集合,如果集合中的元素等于某个值,在这个元素后添加一个元素。

    在迭代器中,只有remove方法,没有add方法。但是在List中有自己特有的迭代器 listIterator

    private class ListItr extends Itr implements ListIterator<E>
    

    ListItr 继承了 Itr,所以 Itr 有的方法都能用。

    List list = new ArrayList();
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    
    // 在list当中有自己特有的迭代器
    ListIterator it = list.listIterator();
    while (it.hasNext()) {
    	String str = (String) it.next();
    	if (str.equals("2")) {
    		// list.add("myxq"); 	//会发生并发修改异常
    		it.add("myxq");
    	}
    }
    System.out.println(list);
    

    ArrayList

    数据结构分析

    数组的大小是固定的,ArrayList 数组扩容的实现:

    查询和修改比较快,通过索引就能找到对应值。

    添加和删除比较慢

    这也就实现了当我们不指定初始化大小的时候,添加第一个元素的时候,数组会扩容为 10.

    添加和删除图示:

    ArrayList 去除集合中重复的元素

    public static ArrayList removeDuplicates(ArrayList list) {
    	// 1.创建一个空的集合
    	ArrayList newList = new ArrayList();
    	// 2.依次取出每一个元素
    	ListIterator it = list.listIterator();
    	while (it.hasNext()) {
    		// 3.每取出一个元素,要先判断新集合当中 ,是否已经包含了该元素
    		Object obj = it.next();
    		// 4.如果已经包含该元素,就不把该元素添加到新集合当中,不包含时才添加到新集合当中
    		if (!newList.contains(obj)) {
    			newList.add(obj);
    		}
    	}
    	return newList;
    }
    
    public static void main(String[] args) {
    	ArrayList list = new ArrayList();
    	list.add("a");
    	list.add("a");
    	list.add("b");
    	list.add("b");
    	list.add("c");
    	list.add("c");
    	list.add("d");
    
    	System.out.println(list);
    	ArrayList newList = removeDuplicates(list);
    	System.out.println(newList);
    }
    

    ArrayList 去除集合中重复的自定义对象元素

    class Student {
    	String name;
    	int age;
    
    	Student(String name, int age) {
    		this.name = name;
    		this.age = age;
    	}
    
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + "]";
    	}
    }
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public class Test {
    
    	public static ArrayList removeDuplicates(ArrayList list) {
    		// 1.创建一个空的集合
    		ArrayList newList = new ArrayList();
    		// 2.依次取出每一个元素
    		ListIterator it = list.listIterator();
    		while (it.hasNext()) {
    			// 3.每取出一个元素,要先判断新集合当中 ,是否已经包含了该元素
    			Object obj = it.next();
    			// 4.如果已经包含该元素,就不把该元素添加到新集合当中,不包含时才添加到新集合当中
    			if (!newList.contains(obj)) {
    				newList.add(obj);
    			}
    		}
    		return newList;
    	}
    
    	public static void main(String[] args) {
    		ArrayList list = new ArrayList();
    		list.add(new Student("张三", 20));
    		list.add(new Student("张三", 20));
    		list.add(new Student("李四", 21));
    
    		System.out.println(list);
    		ArrayList newList = removeDuplicates(list);
    		System.out.println(newList);
    	}
    
    }
    

    以上代码发现并没有去重。

    原因是 contains 是用equals(如果没有重写,默认是Object的equals,比较的是地址)判断有没有相同的元素。

    修改后

    class Student {
    	String name;
    	int age;
    
    	Student(String name, int age) {
    		this.name = name;
    		this.age = age;
    	}
    
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + "]";
    	}
    
    	@Override
    	public boolean equals(Object obj) {
    		if (this == obj)
    			return true;
    		if (obj == null)
    			return false;
    		if (getClass() != obj.getClass())
    			return false;
    		Student other = (Student) obj;
    		if (age != other.age)
    			return false;
    		if (name == null) {
    			if (other.name != null)
    				return false;
    		} else if (!name.equals(other.name))
    			return false;
    		return true;
    	}
    
    }
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public class Test {
    
    	public static ArrayList removeDuplicates(ArrayList list) {
    		// 1.创建一个空的集合
    		ArrayList newList = new ArrayList();
    		// 2.依次取出每一个元素
    		ListIterator it = list.listIterator();
    		while (it.hasNext()) {
    			// 3.每取出一个元素,要先判断新集合当中 ,是否已经包含了该元素
    			Object obj = it.next();
    			// 4.如果已经包含该元素,就不把该元素添加到新集合当中,不包含时才添加到新集合当中
    			if (!newList.contains(obj)) {
    				newList.add(obj);
    			}
    		}
    		return newList;
    	}
    
    	public static void main(String[] args) {
    		ArrayList list = new ArrayList();
    		list.add(new Student("张三", 20));
    		list.add(new Student("张三", 20));
    		list.add(new Student("李四", 21));
    
    		System.out.println(list);
    		ArrayList newList = removeDuplicates(list);
    		System.out.println(newList);
    	}
    }
    

    LinkedList

    数据结构分析

    添加和删除比较快,查询和修改比较慢。

    LinkedList 特有的方法

    // 将指定元素插入此列表的开头。 
    void addFirst(E e) 
    
    // 将指定元素添加到此列表的结尾。
    void addLast(E e) 
    
    // 获取但不移除此列表的头(第一个元素)。 
    E element() 
           
    // 返回此列表的第一个元素。
    E getFirst() 
    
    // 返回此列表的最后一个元素。           
    E getLast() 
    
    // 获取并移除此列表的头(第一个元素)。
    E remove() 
    
    // 移除并返回此列表的第一个元素。
    E removeFirst() 
    
    // 移除并返回此列表的最后一个元素。 
    E removeLast() 
    
    // 将指定元素添加到此列表的末尾(最后一个元素)。
    boolean offer(E e) 			// 类似  add(E e)
    
    // 在此列表的开头插入指定的元素。
    boolean offerFirst(E e) 	// 类似  addFirst(E e)
    
    // 在此列表末尾插入指定的元素。 
    boolean offerLast(E e) 		// 类似  addLast(E e)
    
    // 获取但不移除此列表的头(第一个元素)。
    E peek() 					// 类似  element() 
    
    // 获取但不移除此列表的第一个元素;如果此列表为空,则返回 null。  
    E peekFirst() 				// 类似  getFirst() 
    
    // 获取但不移除此列表的最后一个元素;如果此列表为空,则返回 null。
    E peekLast() 				// 类似  getLast() 
    
    // 获取并移除此列表的头(第一个元素)
    E poll() 					// 类似  remove()
    
    // 获取并移除此列表的第一个元素;如果此列表为空,则返回 null。  
    E pollFirst() 				// 类似  removeFirst()
    
    // 获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。
    E pollLast() 				// 类似  removeLast()
    
    // 从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。
    boolean removeFirstOccurrence(Object o) 
               
    // 从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。 
    boolean removeLastOccurrence(Object o) 
    
    // 返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。元素将按从最后一个(尾部)到第一个(头部)的顺序返回。
    Iterator<E> descendingIterator()
    

    :先进后出

    // 出栈:从此列表所表示的堆栈处弹出一个元素。
    E pop() 					// 底层调用  removeFirst(e);
    
    // 入栈:将元素推入此列表所表示的堆栈。
    void push(E e) 				// 底层调用  addFirst(e);
    

    Vector

    Vector使用很少,一般都使用ArrayList 从1.2开始并到List

    特有的方法

    // 将指定的组件添加到此向量的末尾,将其大小增加 1。
    void addElement(E obj) 
    
    // 返回此向量的组件的枚举。 
    Enumeration<E> elements()   
    

    e.g. 特有的遍历元素

    Vector vc = new Vector();
    vc.add("a");
    vc.add("b");
    vc.add("c");
    
    // 获取所有元素
    Enumeration e = vc.elements();
    while (e.hasMoreElements()) {
    	System.out.println(e.nextElement());
    }
    

    与ArrayList对比

    (1)都是使用数组来实现的

    (2)Vector是线程安全的,内部加了锁;ArrayList当中方法没有加锁

    集合的嵌套

    class Student {
    	String name;
    
    	Student(String name) {
    		this.name = name;
    	}
    }
    
    public class Test {
    	public static void main(String[] args) {
    		/**
    		 * 学科  学科当中是有很多班级
    		 * 班级当中又有很多学生
    		 */
    		Student stu1 = new Student("zs1");
    		Student stu2 = new Student("ls1");
    		// 班级1
    		List<Student> c1 = new ArrayList<>();
    		c1.add(stu1);
    		c1.add(stu2);
    
    		Student stu3 = new Student("zs2");
    		Student stu4 = new Student("ls2");
    		// 班级2
    		List<Student> c2 = new ArrayList<>();
    		c2.add(stu3);
    		c2.add(stu4);
    
    		// 学科 (集合当中又存储集合)
    		List<List<Student>> x = new ArrayList<>();
    		x.add(c1);
    		x.add(c2);
    
    		// 把所有班级当中 的学生姓名打印出来
    		for (List<Student> g : x) {
    			// 取出每一个班级
    			for (Student per : g) {
    				System.out.println(per.name);
    			}
    		}
    
    	}
    }
    
  • 相关阅读:
    SQLSERVER 分区分表
    SQLSERVER 执行计划
    SQL SERVER 自定义函数
    codeforces 414C C. Mashmokh and Reverse Operation(归并排序求逆序对)
    codeforces 414A A. Mashmokh and Numbers(素数筛)
    codeforces 414B B. Mashmokh and ACM(dp)
    bzoj-1012 1012: [JSOI2008]最大数maxnumber(线段树)
    codeforces 665E E. Beautiful Subarrays(trie树)
    codeforces 667D D. World Tour(最短路)
    codeforces 667C C. Reberland Linguistics(dp)
  • 原文地址:https://www.cnblogs.com/xzh0717/p/11284708.html
Copyright © 2011-2022 走看看