container,Collection接口,Iterator接口,list接口,set接口

目录

1. 容器(container)

容器

概念

使用数组手写简单容器

泛型<>

为什么需要泛型

泛型的好处

2. Collection接口

collection遍历

List接口

ArrayList

ArrayList存储对象

LinkedList

Vector与Stack

三者比较

Set接口

HashSet

TreeSet

equal和hashcode的关系和原理

3. Iterator接口

ListIterator接口


  • 1. 容器(container)

  • 容器

  • 概念

之前我们学习过数组,数组是相同数据类型的有序集合,可以在其中放置对象或基本类型数据,说白了就是容器。数组是一种简单的线性序列,可以快速的访问数组元素,效率高。如果从效率和类型检查的角度讲,数组是最好的。

但是从数组长度一旦确定,不可改变,因此,不灵活:容量需要事先定义好,不能随着需求的变化而扩容。

因此,数组远远不能满足我们的需求。我们需要一种灵活的,容量可以随时扩充的容器来装载我们的对象。这就是我们今天要学习的容器类,或者叫集合框架。

  • 使用数组手写简单容器

package day13.collection;

/*
 * 使用数组手写简单容器
 * 	
 */
public class MyContainerDemo2 {
	public static void main(String[] args) {
		MyCon my = new MyCon();
		my.add("98k");
		my.add("AWM");
		my.add("M24");
		System.out.println("容器长度: " + my.size);
		System.out.println("-------------------");
		my.remove(0);
		my.revamp(2, "M416");
		for (String string : my.arr) {
			System.out.println(string);
		}
	}
}

/*
 * 自定义容器
 */
class MyCon {
	// 定义容器索引
	String[] arr;
	// 容器长度
	int size;

	// 构造器
	public MyCon() {
		// 创建对象时就应存在一个数组
		arr = new String[0];
	}

	// 增 --add方法
	public void add(String ele) {
		// 存储原数组
		String[] temp = arr;
		arr = new String[size + 1];
		for (int i = 0; i < temp.length; i++) {
			arr[i] = temp[i];
		}
		arr[size] = ele;
		size++;
	}

	// 删
	public void remove(int index) {
		if (index < 0 || index >= size) {
			System.out.println("Error");
			return;
		}
		String[] temp = arr;
		arr = new String[size - 1];
		for (int i = 0; i < size; i++) {
			if (i >= index) {
				if (i == index) {
					continue;
				}
				arr[i - 1] = temp[i];

			} else {
				arr[i] = temp[i];
			}
		}
		// 删除
		size--;
	}

	// 获取
	public String get(int index) {
		if (index < 0 || index >= size) {
			return "你越界了朋友";
		}
		return arr[index];

	}

	// 改
	public void revamp(int index, String str) {
		for (int i = 0; i < arr.length; i++) {
			if (index < 0 || index > size - 1) {
				System.out.println("没有此数据");
				return;
			}
			arr[index] = str;
		}

	}
}
  • 泛型<>

  • 为什么需要泛型

 JDK1.4 以前类型不明确:

         装入集合的类型都被当作Object 对待,从而失去自己的实际类型。

         从集合中取出时往往需要转型,效率低,容易产生错误。

  • 泛型的好处

 增强程序的可读性和稳定性。

 使用泛型,保留了容器中元素的类型,安全省心的使用容器。

 注意:没有必要引入泛型的复杂性。

  • 2. Collection接口

 * Collection 接口     规定了容器类的一些使用规则,可以存储无序不可重复的数据
 *                              容器中只能放引用数据类型,基本数据类型会自动装箱
 * 
 * 1.特性  无序不可重复 接口
 * 2.方法
 * 3.遍历

package day13.collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

public class CollectionDemo3 {
	public static void main(String[] args) {
		//1.创建容器
		Collection c=new ArrayList();
		/*
		 * 2.添加元素
		 * boolean add(E e) 
			          确保此 collection 包含指定的元素(可选操作)。 
		   boolean addAll(Collection<? extends E> c) 
			          将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。 
		 */
		c.add("清华大学");
		c.add("北京大学");
		Collection c2=new ArrayList();
		c2.add("哈工大");
		c2.add("佳木斯大学");
		c2.add(1); //Integer 自动装箱
		System.out.println(c.size());
		c.addAll(c2);
		
		/*
		 * 3.获取
		 *  int size() 
          		返回此 collection 中的元素数。 
          	boolean isEmpty() 
          		如果此 collection 不包含元素,则返回 true。 
		 */
		System.out.println(c.size());
		System.out.println("判断是否为空:"+c.isEmpty());
		System.out.println(c);
		
		/*
		 * 4.删除
		 *  void clear() 
          		移除此 collection 中的所有元素(可选操作)。 
          	boolean remove(Object o) 
          		从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。 
          	boolean removeAll(Collection<?> c) 
          		移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。 
          	boolean retainAll(Collection<?> c) 
          		仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。 
		 */
		System.out.println(c.size());
		System.out.println("remove:"+c.remove("清华大学"));
		System.out.println(c.size());
		//System.out.println("removeAll:"+c.removeAll(c2));
		System.out.println("removeAll:"+c.retainAll(c2));
		System.out.println(c.size());
//		c.clear();
		System.out.println(c.size());
		System.out.println("判断是否为空:"+c.isEmpty());
		
		/*
		 *  Object[] toArray() 
          		返回包含此 collection 中所有元素的数组。 
		 */
		 Object[] obj=c.toArray();
		 System.out.println(Arrays.toString(obj));
		
		/*
		 * 5.是否包含
		 *  boolean contains(Object o) 
          		如果此 collection 包含指定的元素,则返回 true。 
		 */
		System.out.println(c.contains("佳木斯大学"));
		
		/*
		 * 6.遍历
		 * 	foreach
		 *  迭代器
		 */
		
	}
}
  • collection遍历

 * Collection 遍历
 *         两种:1)增强for
 *              2)迭代器

package day13.collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

/*
 * Collection 遍历
 * 		两种:1)增强for
 * 			 2)迭代器
 */
public class CollectionDemo4 {
	public static void main(String[] args) {
		Collection c = new ArrayList();
		c.add("拇指");
		c.add("食指");
		c.add("中指");
		c.add("无名指");
		c.add("小手指");
		
		//foreach
		for (Object obj : c) {
			System.out.println(obj);
		}
		
		/*迭代器
		 * 1.获取一个迭代器对象,凡是实现了Collection接口的;类都有iterator()
		 * 2.判断是否有下一个元素
		 * 3.如果有用next()方法获取
		 */
		Iterator it =c.iterator();
		while (it.hasNext()) {
			Object o = it.next();
			System.out.println(o);
		}
	}
}
  • List接口

 * List
 *     特性: 有序  可重复
 *     方法:
 *     遍历:

package day13.test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/*
 * 遍历
 * 如果容器中存在火,那就添加一个元素灭火器
 * 
 * ConcurrentModificationException-----foreach&迭代器(底层是foreach)
 * 	方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
 */
public class ListTest1 {
	public static void main(String[] args) {
		List<String> ls = new ArrayList();
		// 增加
		ls.add("金");
		ls.add("木");
		ls.add("水");
		ls.add("火");
		ls.add("土");

		// 1.----------for
		for (int i = 0; i < ls.size(); i++) {
			if (ls.get(i).equals("火")) {
				ls.add("灭火器1");
			}
			// System.out.println(ls.get(i));
		}
		System.out.println(ls);
		System.out.println("↓--↓--↓---↓---↓---↓---↓--↓--↓");

		// ----------foreach
		for (String str : ls) {
			System.out.println(str);
		}
		System.out.println("↓--↓--↓---↓---↓---↓---↓--↓--↓");

		/*-------------迭代器
		 * 解决并发增加问题:使用 ListIterator
		 */
		ListIterator it = ls.listIterator();
		while (it.hasNext()) {
			if (it.next().equals("火")) {
				it.add("灭火器2");
			}
		}
		System.out.println(ls);
	}
}
  • ArrayList

 * ArrayList : 有序的  可重复的  线程不安全
 *                底层由可变数组结构实现
 * 优点:查询,以及随机获取效率高
 * 缺点:增加,删除效率低
 *         动态扩容:使用copyof进行扩容,新数组的大小是原数组的1.5倍
 * Vector:线程安全的,效率低 ,每次扩容原来的2倍

package day13.list;

import java.util.ArrayList;
import java.util.ListIterator;

public class ArrayListDemo08 {
	public static void main(String[] args) {
		ArrayList<String> ls=new ArrayList();  //构造一个初始容量为 10 的空列表。
		System.out.println(ls);
		
		ls.add("钢铁侠");
		ls.add("雷神");
		ls.add("灭霸");
		ls.add("美国队长");
		
		System.out.println(ls.indexOf("雷神"));
		
		//1.获取迭代器
		 ListIterator li=ls.listIterator();
		 //判断
		 while(li.hasNext()){
			 System.out.println(li.next());
		 }
		 System.out.println("------------------");
		 while(li.hasPrevious()){
			 System.out.println(li.previous());
		 }
	}
}
  • ArrayList存储对象

package day13.list;

import java.util.ArrayList;
import java.util.List;

/*
 * ArrayList存储对象
 */
public class ArrayListTest09 {
	public static void main(String[] args) {
		//创建容器
		List<Person> ls=new ArrayList();
		ls.add(new Person("张三",18));
		ls.add(new Person("李四",19));
		System.out.println(ls.indexOf(new Person("李四",19)));  //-1 因为Person中没有重写equals方法
		
		List<String> ls2=new ArrayList();
		ls2.add(new String("哈哈"));
		System.out.println(ls2.indexOf(new String("哈哈"))); // 0  因为String类型中重写了squals方法
	}
}

class Person{
	private String name;
	private int age;
	
	public Person() {
		// TODO Auto-generated constructor stub
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
}
  • LinkedList

 * LinkedList  有序的  可重复的  线程安全
 *     实现结构:是由链表结构实现的
 *  优点:插入,删除效率高
 *  缺点:查询,随机获取效率低
 *  新增了一些操作类表头和类表尾的方法

package day13.test;

import java.util.LinkedList;

public class LinkedListTest {
	public static void main(String[] args) {
		LinkedList<String> ls = new LinkedList();
		ls.add("哈哈");
		ls.add("呵呵");
		ls.add("嘿嘿");
		ls.addFirst("嚯嚯");
		
		System.out.println(ls);
		System.out.println(ls.clone());
		System.out.println(ls.contains("哈哈"));//true
		System.out.println(ls.descendingIterator().next());//嘿嘿
		
	}
}

  • Vector与Stack

  • 三者比较

LinkedList:底层用双向链表实现的List。特点:查询效率低,增删效率高,线程不安全。

ArrayList:底层用数组实现的List。特点:查询效率高,增删效率低,线程不安全。

Vector:底层用数组实现的List,特点:线程安全。

如何选用?

       线程安全用Vector。

       线程不安全,查找较多用ArrayList。增加或删除元素较多用LinkedList

  • Set接口

package day13.set;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

/*
 * Set 接口  无序的   不可重复的
 */
public class SetDemo11 {
	public static void main(String[] args) {
		Set<Character> set=new HashSet();
		set.add('a');
		set.add('b');
		set.add('c');
		set.add('c'); //不能重复
		set.add('d'); //不能重复
		set.add('e'); //不能重复
		System.out.println(set.size());
		set.remove('c');
		System.out.println(set);  //[d, e, b, a]  不会按照添加的顺序存储,但是一旦储存顺序就确定了
		
		//遍历
		//----foreach
		for(char c:set){
			System.out.println(c);
		}
		
		//----迭代器
		Iterator it=set.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}
  • HashSet

 * HashSet 
 *     无序的   不可重复的
 *     由哈希表的数据结构存储的  哈希表=数组+链表
 *  优点:查询  增加  删除  效率高
 *  缺点:无序的
 *  
 *  去重:从写hashcode 与 equals ---- alt+shif+s ->h 按业务更改
 *      先调用hashcode,如果计算出来的位置不相同,默认就是两个对象
 *          如果hashcode值相同,再去调用equals,去比较内容

package day13.set;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

public class HashSetDemo12 {
	public static void main(String[] args) {
		HashSet<User> set=new HashSet<>();
		set.add(new User("李健",40));
		set.add(new User("谢霆锋",41));
		set.add(new User("李健",40));
		System.out.println(set.size());
		for(User u:set){
			System.out.println(u.hashCode());
		}
		
		TreeSet tr=new TreeSet();
		tr.add("c");
		tr.add("b");
		tr.add("哈哈");
		tr.add("a");
		tr.add("呵呵");
		tr.add("e");
		System.out.println(tr);
		System.out.println(tr.ceiling("b"));  //c
		System.out.println(tr.floor("b"));  //a
		System.out.println(tr.higher("b"));  //c
		System.out.println(tr.pollFirst());  //c
	}
}


class User{
	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public User(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		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;
		User other = (User) 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;
	}
	
	
}
  • TreeSet

 *  TreeSet 
 *   有序的(排序--升序)  不可重复的
 *   使用二叉树结构存储

  • equal和hashcode的关系和原理

      1. Hashcode并不是内存地址,是内存地址转换而来的。系统通过它也可以确定内存地址。

     2. hashcode方法主要用在集合框架中,目的是为了快速比较两个对象是否相等,因为集合框架中的对象很多,每个都使用equals比较效率很差。

每个对象都有一个hashcode,规定:

      1、内容相同的对象hashcode肯定相等

      2、内容不相同的对象hashcode可能相等也可能不相等

所以如果两个对象的hashcode不相等则两个对象的内容肯定不相等,这样就不必一个一个去比较属性的值了,从而提高对象比较的速度。

  • 3. Iterator接口

为了遍历容器方便,所有实现了Collection接口的容器类都有一个iterator方法用以返回一个实现了Iterator接口的对象。Iterator对象称作迭代器,用以方便的实现对容器内元素的遍历操作。

使用迭代器时,分三步走策略,
第一步:获取对象
第二步:判断是否存在下一个
第三步:获取元素

见List接口的使用迭代器遍历部分

  • ListIterator接口

 *     ConcurrentModificationException

 *     方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

       解决并发增加问题:使用 ListIterator

        //1.获取迭代器
         ListIterator li=ls.listIterator();
         //判断
         while(li.hasNext()){
             if(li.next().equals("灭霸")){
                 li.add("惊奇队长");
             }
         }
         System.out.println(ls);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值