Collection集合(1)

---|Collection: 单列集合
	---|List: 有存储顺序, 可重复
		---|ArrayList:	数组实现, 查找快, 增删慢
由于是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素. 所以慢。数组是可以直接按索引查找, 所以查找时较快
		---|LinkedList:	链表实现, 增删快, 查找慢
由于链表实现, 增加时只要让前一个元素记住自己就可以, 删除时让前一个元素记住后一个元素, 后一个元素记住前一个元素. 这样的增删效率较高但查询时需要一个一个的遍历, 所以效率较低
		---|Vector:	和ArrayList原理相同, 但线程安全, 效率略低
和ArrayList实现方式相同, 但考虑了线程安全问题, 所以效率略低
	---|Set: 无存储顺序, 不可重复
		---|HashSet
		---|TreeSet
		---|LinkedHashSet
---| Map: 键值对
		---|HashMap
		---|TreeMap
		---|HashTable
		---|LinkedHashMap

1. Collection 接口:

这个接口的特点是:元素是 Object。换而言之,Collection 接口所有的子接口,以及其实现类,所管理的元素单位都是对象。

1.1.  Collection 接口的两个子接口:

 

     其中一个子接口为 List 接口。List 接口的特点,是 List中元素有顺序,可以重复。所谓元素有顺序,指的是说,几个元素放入 List 的先后顺序,就是这几个元素在 List 中的排列顺序。通过集合中元素的顺序,我们可以区分出集合中第 1 个元素,第 2 个元素……

     Collection 还有一个子接口 Set 接口。Set 接口的特点是元素不可以重复,无顺序。

 2. Map 接口:

与 Collection 接口对应,Map 接口所管理的元素不是对象,而是“键值对”。什么是键值对呢?“键”和“值”各是一个对象,这两个对象之间,存在着对应的关系,我们可以通过键对象,来找到对应的值对象。在 Map 中,键对象是唯一的,不可重复的,而键对象所对应的值对象是可以重复的。

Set 接口有个子接口 SortedSet。这个接口具有 Set 的特点,其中的元素不能够重复。但是这个接口与 SortedSet 不同的地方在于,这个接口中的元素会按照一定的排序规则,自动对集合中的元素排序。
Map 有个子接口 SortedMap。这个接口与 Map 一样,管理的元素是键值对,键不能重复,值可以重复。所不同的是,在这个接口中,键对象会按照一定的排序规则,自动排序

特点:
Collection中描述的是集合共有的功能(CRUD)
        List可存放重复元素,元素存取是有序的
        Set不可以存放重复元素,元素存取是无序的

java.util.Collection
          ---| Collection           描述所有接口的共性
                 ----| List接口     可以有重复元素的集合
                 ----| Set  接口    不可以有重复元素的集合

 

1.2 什么时候该使用什么样的集合

 

Collection       我们需要保存若干个对象的时候使用集合。

 

 

          如果我们需要保留存储顺序, 并且保留重复元素, 使用List.
List           如果查询较多, 那么使用ArrayList
              如果存取较多, 那么使用LinkedList
              如果需要线程安全, 那么使用Vector

       如果我们不需要保留存储顺序, 并且需要去掉重复元素, 使用Set.
              如果我们需要将元素排序, 那么使用TreeSet

Set            如果我们不需要排序, 使用HashSet, HashSet比
              TreeSet效率高.
              如果我们需要保留存储顺序, 又要过滤重复元素, 那么使用LinkedHashSet

3 Collection

1、 接口特点
Collection 接口的特点是元素是 Object。遇到基本类型数据,需要转换为包装类对象。

 

2、 基本操作
Collection 接口中常用的基本操作罗列如下:

 

   1) boolean add(Object o)
       这个操作表示把元素加入到集合中。add 方法的返回值为 boolean 类型。如果元素
  加入集合成功,则返回 true,否则返回 false。

   2 ) addAll() 
         将指定集合中的元素添加到调用该方法和集合中

   3)  boolean contains(Object o)
       这个方法判断集合中是否包含了 o 元素。

 

   4 ) containsAll()   判断集合中是否包含指定集合
                       使用equals()判断两个对象是否相等

   5) boolean isEmpty()
       这个方法判断集合是否为空。

   6)  Iterator iterator()
       这个方法很重要,可以用来完成集合的迭代遍历操作。

   7 )  boolean remove(Object o)
       remove 方法表示从集合中删除 o 元素。返回值表示删除是否成功。

    8 ) removeAll()     将指定集合中的元素删除

    9)  void clear()
       clear 方法清空集合。

    10) int size()
       获得集合中元素的个数。

3.1   增加:

 

public static void main(String[] args) {
		Collection list = new ArrayList();
		// 增加:add() 将指定对象存储到容器中
		list.add("计算机网络");
		list.add("现代操作系统");
		list.add("java编程思想");
		System.out.println(list);
		// [计算机网络, 现代操作系统, java编程思想]
		
		// 增加2 将list容器元素添加到list2容器中
		Collection list2 = new ArrayList();
		list2.add("java核心技术");
		list2.addAll(list);
		list2.add("java语言程序设计");
		System.out.println(list2);
		// [java核心技术, 计算机网络, 现代操作系统, java编程思想, java语言程序设计]
	}

3..2 删除:

 

// 删除1 remove
		boolean remove = list2.remove("java核心技术");
		System.out.println(remove); // true
		System.out.println(list2); //
		//删除2 removeAll() 将list中的元素删除
		boolean removeAll = list2.removeAll(list);
		System.out.println(removeAll);//true
		System.out.println(list2);//[java语言程序设计]

3.3  修改:

 

public static void main(String[] args) {
		Collection list = new ArrayList();
		// 增加:add() 将指定对象存储到容器中
		list.add("计算机网络");
		list.add("现代操作系统");
		list.add("java编程思想");
		list.add("java核心技术");
		list.add("java语言程序设计");
		System.out.println(list);
		// 修改 clear() 清空集合中的所有元素
		list.clear();
		System.out.println(list); //[] 
	}

3.4  判断: 

 

public static void main(String[] args) {
		Collection list = new ArrayList();
		// 增加:add() 将指定对象存储到容器中
		list.add("计算机网络");
		list.add("现代操作系统");
		list.add("java编程思想");
		list.add("java核心技术");
		list.add("java语言程序设计");
		System.out.println(list);
		
		boolean empty = list.isEmpty();
		System.out.println(empty);// false
		boolean contains = list.contains("java编程思想");
		System.out.println(contains);// true
		Collection list2 = new ArrayList();
		list2.add("水许传");
		boolean containsAll = list.containsAll(list2);
		System.out.println(containsAll);// false

	}

3.5  获取:

 

public static void main(String[] args) {
		Collection list = new ArrayList();
		// 增加:add() 将指定对象存储到容器中
		list.add("计算机网络");
		list.add("现代操作系统");
		list.add("java编程思想");
		list.add("java核心技术");
		list.add("java语言程序设计");
		System.out.println(list);
		// 获取  集合容器的大小 
		int size = list.size();
		System.out.println(size);   }
3.6  集合中添加自定义对象:
分析:
1:Person类
   1:姓名和年龄
   2:重写hashCode和equals方法
      1:如果不重写,调用Object类的equals方法,判断内存地址,为false
          1:如果是Person类对象,并且姓名和年龄相同就返回true
      2:如果不重写,调用父类hashCode方法
          1:如果equals方法相同,那么hashCode也要相同,需要重写hashCode方法
      3:重写toString方法
          1:不重写,直接调用Object类的toString方法,打印该对象的内存地址

如果不重写自定义的对象里面的hashCode和equals方法,定义两个参数一样的对象,但是他们的hashCode是不一样的

Person类

class Person {
	private String name;
	private int age;

	public Person() {

	}

	public Person(String name, int age) {

		this.name = name;
		this.age = age;
	}

	@Override
	public int hashCode() {
		return this.name.hashCode() + age;
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof Person)) {
			return false;
		}
		Person p = (Person) obj;
		return this.name.equals(p.name) && this.age == p.age;
	}

	@Override  
	public String toString() {
		return "Person :name=" + name + ", age=" + age;
	}

}
public static void main(String[] args) {
       Person p1 = new Person("张三", 19);
       Person p2 = new Person("李四", 20);
       Person p3 = new Person("王五", 18);
       Collection list = new ArrayList();
       list.add(p1);
       list.add(p2);
       list.add(p3);
       // isEmpty() 判断集合是否为空
       boolean empty = list.isEmpty();
       System.out.println(empty);
       // 返回集合容器的大小
       int size = list.size();
       System.out.println(size);
        // contains()判断集合何中是否包含指定对象
       boolean contains = list.contains(p1);
       System.out.println(contains);
 
       // remove(); 将指定的对象从集合中删除
       list.remove(p1);
       
       // clear() 清空集合中的所有元素
       list.clear();
       System.out.println(list);
 
    }

//使用集合存储自定义对象2

//使用集合存储自定义对象2
class Book {
	private String name;
	private double price;

	public Book() {

	}

	public Book(String name, double price) {
		this.name = name;
		this.price = price;
	}

	public String getName() {
		return name;
	}

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

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}

	@Override
	public int hashCode() {
		return (int) (this.name.hashCode() + price);
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof Book)) {
			return false;
		}
		Book book = (Book) obj;
		return this.name.equals(book.name) && this.price == book.price;
	}

	@Override
	public String toString() {
		return "book:@ name:" + this.name + ", price:" + this.price;
	}
}
public class Demo1 {
	public static void main(String[] args) {
		Collection col = new ArrayList();
		col.add(new Book("think in java", 100));
	col.add(new Book("core java", 200));		 System.out.println(col);
	}
}

Collection 没有直接的实现类。也就是说,某些实现类实现了 Collection 接口的子接口,
例如 List、Set,这样能够间接的实现 Collection 接口。但是没有一个实现类直接实现Collection 接口却没有实现其子接口。

 

4 List

4.1 List  特点和基本操作

 

     List 接口的特点:元素是对象,并且元素有顺序,可以重复。

     可以把 List 当做是一个列表。例如,如果让我们列出历任美国总统,我们必然会按照顺序说出每一任的人名,对于连任的总统,在这个列表中就会出现多次。这样的结构就是一个典型的 List:元素有顺序,并且可以重复出现。
     对于 List 而言,元素的所谓“顺序”,指的是每个元素都有下标。因此,List 的基本操作,除了从 Collection 接口中继承来的之外,还有很多跟下标相关的操作。

基本操作罗列如下:

1)boolean add(Object o) / void add(int index, Object element)
     在 List 接口中有两个重载的 add 方法。第一个 add 方法是从 Collection 接口中继承
     而来的,表示的是把 o 元素加入到 List 的末尾;第二个 add 方法是 List 接口特有
     的方法,表示的是把元素 element 插入到集合中 index 下标处。

2)boolean addAll(int index, Collection c) 指定位置添加集合

3) Object get(int index) / Object set(int index, Object element)
     get 方法获得 List 中下标为 index 的元素,set 方法把 List 中下标为 index 的元素设
     置为 element。
     利用这两个方法,可以对 List 根据相应下标进行读写。

 

4)lastIndexOf(Object o) 返回最后出现的指定元素的角标

5) int indexOf(Object o)
     这个方法表示在 List 中进行查找。如果 List 中存在 o 元素,则返回相应的下标。
     如果 List 中不存在 o 元素,则返回-1。
     这个方法可以用来查找某些元素的下标。

除此之外,List 接口中还有一些诸如 size、clear、isEmpty 等方法,这些方法与介绍Collection 接口中的相应方法含义相同

4.2  增加:

 

public static void main(String[] args) {
List list = new ArrayList();		// 增加:add() 将指定对象存储到容器中
		list.add("计算机网络");
		list.add("现代操作系统");
		list.add("java编程思想");
		list.add("java核心技术");
		list.add("java语言程序设计");
		System.out.println(list);
		// add,在0角标位置添加一本书
		list.add(0, "舒克和贝塔");
		System.out.println(list);
		// 在list2集合的1角标位置添加list集合元素
		List list2 = new ArrayList();
		list2.add("史记");
		list2.add("资治通鉴");
		list2.add("全球通史");
		boolean addAll = list2.addAll(1, list);
		System.out.println(addAll); //true	
	 System.out.println(list2);
	}
/*
输出:
[计算机网络, 现代操作系统, java编程思想, java核心技术, java语言程序设计]
[舒克和贝塔, 计算机网络, 现代操作系统, java编程思想, java核心技术, java语言程序设计]
true
[史记, 舒克和贝塔, 计算机网络, 现代操作系统, java编程思想, java核心技术, java语言程序设计, 资治通鉴, 全球通史]

*/

 

4.3  删除:

 

public static void main(String[] args) {
		List list = new ArrayList();
		// 增加:add() 将指定对象存储到容器中
		list.add("计算机网络");
		list.add("现代操作系统");
		list.add("java编程思想");
		list.add("java核心技术");
		list.add("java语言程序设计");
		System.out.println(list);
		// 删除0角标元素
		Object remove = list.remove(0);
		System.out.println(remove);
	}

4.4  修改:

 

public static void main(String[] args) {
		List list = new ArrayList();
		// 增加:add() 将指定对象存储到容器中
		list.add("计算机网络");
		list.add("现代操作系统");
		list.add("java编程思想");
		list.add("java核心技术");
		list.add("java语言程序设计");
		System.out.println(list);
		// 修改2角标位置的书,返回的原来2角标位置的书
		Object set = list.set(2, "边城");
		System.out.println(set); //java编程思想
		System.out.println(list); 
		
	}

4.5   查找

 

	List list = new ArrayList();
		// 增加:add() 将指定对象存储到容器中
		list.add("计算机网络");
		list.add("现代操作系统");
		list.add("java编程思想");
		list.add("java核心技术");
		list.add("java语言程序设计");
		System.out.println(list);
		// 查找: E get(int index)  注意角标越界
		Object set = list.get(list.size() - 1);
		System.out.println(set); // java语言程序设计
		System.out.println(list);
list.get(list.size()); //IndexOutOfBoundsException
	}

4.6  查找2

 

public static void main(String[] args) {
		List list = new ArrayList();
		// 增加:add() 将指定对象存储到容器中
		list.add("计算机网络");
		list.add("现代操作系统");
		list.add("java编程思想");
		list.add("java核心技术");
		list.add("java语言程序设计");
		list.add("java编程思想");
		System.out.println(list);
		// 查找: E get(int index) 注意角标越界
		Object set = list.get(list.size() - 1);
		System.out.println(set); // java语言程序设计
		System.out.println(list);
		// list.get(list.size()); //IndexOutOfBoundsException

		// indexOf(Object o) 返回第一次出现的指定元素的角标
		int indexOf = list.indexOf("java编程思想");
		System.out.println(indexOf); // 2
		// 没有找到,返回-1
		int indexOf2 = list.indexOf("三国志");
		System.out.println(indexOf2); // -1

		// lastIndexOf 返回最后出现的指定元素的角标
		int lastIndexOf = list.lastIndexOf("java编程思想");
		System.out.println(lastIndexOf); // 5
	}


        
4.2  遍历

      首先,为了能使用 List 接口,必须先简单介绍一个 List 接口的实现类:ArrayList。这个
类使用数组作为底层数据结构,实现了 List 接口,我们使用这个类来演示应该如何对 List
进行遍历。
      由于 List 接口具有下标,因此我们用类似对数组遍历的方式,采用 for 循环对 List 进行
遍历。示例代码如下:

 

 

public class TestArrayList {
	   public static void main(String args[]){
		List list = new ArrayList();
		list.add("hello");
		list.add("world");
		list.add("java");
		list.add("study");

		for(int i = 0; i<list.size(); i++){
		   System.out.println(list.get(i));
		}
     }
}
      可以看出,利用 List 接口中的 size 方法,我们可以得出集合中元素的个数,那么集合
中元素的下标范围就是 0 ~ size-1 。 继而我们可以通过 get 方法,根据下标获得相应的元素。
利用这种方法,我们就可以遍历一个 List。

 

      除此之外,List 接口还有另外一种遍历方式:迭代遍历。

5.  迭代遍历

      迭代遍历是 Java 集合中的一个比较有特色的遍历方式。这种方法被用来遍历 Collection接口,也就是说,既可以用来遍历 List,也可以用来遍历 Set。
     使用迭代遍历时,需要调用集合的 iterator 方法。这个方法在 Collection 接口中定义,也就是说,List 接口也具有 iterator 方法。
      这个方法的返回值类型是一个 Iterator 类型的对象。Iterator 是一个接口类型,接口类型没有对象,由此可知,调用 iterator 方法,返回的一定是 Iterator 接口的某个实现类的对象。这是非常典型的把多态、接口用在方法的返回值上面。
      Iterator 接口表示的是“迭代器”类型。利用迭代器,我们可以对集合进行遍历,这种遍历方式即称之为迭代遍历。

       例如,有如下代码:

 

 

 

public class TestArrayList {
	   public static void main(String args[]){
	        List list = new ArrayList();
		list.add("hello");
		list.add("world");
		list.add("java");
		list.add("study");

		Iterator iter = list.iterator();
       }
    }

此时,在集合中有四个元素:hello、world、java、study。示意图如下:

 

 

 

    在调用 list 的 iterator 方法之后,返回一个 Iterator 类型的对象。这个对象就好像一个指
针,指向第一个元素之前。如下图:

在迭代器中定义了两个方法:

       boolean hasNext()
这个方法返回一个 boolean 类型,表示判断迭代器右方还有没有元素。对于上面这种情况,对迭代器调用 hasNext()方法,返回值为 true。

       Object next()
这个方法,会把迭代器向右移动一格。同时,这个方法返回一个对象,这个对象就是迭代器向右移动时,跳过的那个对象。如下图:

调用一次 next 方法之后,迭代器向右移动一位。在向右移动的同时,跳过了“hello”这个元素,于是这个元素就作为返回值返回。

    我们可以再持续的调用 next()方法,依次返回“world”,“java”,“study”对象,直至hasNext()方法返回 false,意味着迭代器已经指向了集合的末尾,遍历过程即结束。利用 Iterator 接口以及 List 中的 iterator 方法,可以对整个 List 进行遍历。代码如下:

 

public class TestArrayList {
	   public static void main(String args[]){
		List list = new ArrayList();
		list.add("hello");
		list.add("world");
		list.add("java");
		list.add("study");

		Iterator iter = list.iterator();
		while(iter.hasNext()){
		   Object value = iter.next();
		   System.out.println(value);
	}
    }
}

      迭代遍历往往是用 while 循环来实现的。利用 hasNext 方法返回值作为循环条件,判断List 后面是否还有其他元素。在循环体中,调用 next 方法,一方面把迭代器向后移动,另外一方面一一返回 List 中元素的值

6  ArrayList

----| Iterable
     ----| Collection
          ------| List
                 ---------| ArrayList  底层采用数组实现,默认10。
                                       每次增长60%,((oldCapacity * 3)/2 + 1) 查询快,增删慢。
                 ---------| LinkedList    

ArrayList:实现原理:

数组实现, 查找快, 增删慢
数组为什么是查询快?

 

         因为数组的内存空间地址是连续的.ArrayList底层维护了一个Object[] 用于存储对象,默认数组的长度是10。可以通过 new ArrayList(20)显式的指定用于存储对象的数组的长度。
       当默认的或者指定的容量不够存储对象的时候,容量自动增长为原来的容量的1.5倍。由于ArrayList是数组实现, 在增和删的时候会牵扯到数组增容, 以及拷贝元素. 所以慢。数组是可以直接按索引查找, 所以查找时较快可以考虑,假设向数组的0角标未知添加元素,那么原来的角标位置的元素需要整体往后移,并且数组可能还要增容,一旦增容,就需要要将老数组的内容拷贝到新数组中.所以数组的增删的效率是很低的.

 
练习:去除ArrayList集合中重复元素
               1:存入字符串元素
               2:存入自定义对象元素(如Perosn对象)
原理:
     循环遍历该集合,每取出一个放置在新的集合中,放置之前先判断新的集合是否以包含了新的元素。

 

思路:
   存入人的对象.
   1先定义person
   2将该类的实例存入集合
   3将对象元素进行操作.注意:自定义对象要进行复写toString equals方法.
   为什么?因为objectperson的父类,object中的toString返回的是哈希值,object类中equals
 方法比较的是对象的地址值.
 思路
   1存入字符串对象
   2存入自定义对象person
   2创建容器,用于存储非重复元素
   3对原容器进行遍历,在遍历过程中进行判断遍历到的元素是否在容器中存在.(contains)
   4如果存在,就不存入,否则存入.
   5返回新容器

 

public class Demo6 {
	public static void main(String[] args) {
		ArrayList arr = new ArrayList();
		Person p1 = new Person("jack", 20);
		Person p2 = new Person("rose", 18);
		Person p3 = new Person("rose", 18);
		arr.add(p1);
		arr.add(p2);
		arr.add(p3);
		System.out.println(arr);
		ArrayList arr2 = new ArrayList();
		for (int i = 0; i < arr.size(); i++) {
			Object obj = arr.get(i);
			Person p = (Person) obj;
			if (!(arr2.contains(p))) {
				arr2.add(p);
			}
		}
		System.out.println(arr2);
	}
}

class Person {
	private String name;
	private int age;

	public Person() {

	}

	public Person(String name, int age) {

		this.name = name;
		this.age = 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;
	}

	@Override
	public int hashCode() {
		return this.name.hashCode() + age * 37;
	}

	@Override
	public boolean equals(Object obj) {
		if (!(obj instanceof Person)) {
			return false;
		}
		Person p = (Person) obj;

		return this.name.equals(p.name) && this.age == p.age;
	}

	@Override
	public String toString() {
		return "Person@name:" + this.name + " age:" + this.age;
	}

}

7  LinkedList

 

----| Iterable
     ----| Collection
          ------| List
                 ---------| ArrayList  底层采用数组实现,默认10。每次增长
                                       60%,((oldCapacity * 3)/2 + 1) 查询快,增删慢。
                 ---------| LinkedList  底层采用链表实现,增删快,查询慢。

 

LinkedList:链表实现, 增删快, 查找慢

 

     由于LinkedList:在内存中的地址不连续,需要让上一个元素记住下一个元素.所以每个元素中保存的有下一个元素的位置.虽然也有角标,但是查找的时候,需要从头往下找,显然是没有数组查找快的.但是,链表在插入新元素的时候,只需要让前一个元素记住新元素,让新元素记住下一个元素就可以了.所以插入很快.
     由于链表实现, 增加时只要让前一个元素记住自己就可以, 删除时让前一个元素记住后一个元素, 后一个元素记住前一个元素. 这样的增删效率较高。但查询时需要一个一个的遍历, 所以效率较低。

 

特有方法

 

1:方法介绍
     addFirst(E e) 
     addLast(E e) 
     getFirst() 
     getLast() 
     removeFirst() 
     removeLast() 
     如果集合中没有元素,获取或者删除元
     素抛:NoSuchElementException

2:数据结构
         1:栈 (1.6)
              先进后出
              push() 
              pop()
         2:队列(双端队列1.5)
              先进先出
              offer()
              poll()

3:返回逆序的迭代器对象      
             descendingIterator()   返回逆序的迭代器对象

基本方法

import java.util.Iterator;
import java.util.LinkedList;

public class Demo3 {
	public static void main(String[] args) {
		LinkedList list = new LinkedList();
		list.add("西游记");
		list.add("三国演义");
		list.add("石头记");
		list.add("水浒传");
		list.add("全球通史");
		list.addFirst("史记");
		list.addLast("呐喊");
		// list.addFirst(null);
		// list.addLast(null);
		System.out.println(list);
		// 获取指定位置处的元素。
		String str = (String) list.get(0);
		// 返回此列表的第一个元素。
		String str2 = (String) list.getFirst();
		System.out.println(str.equals(str2));

		// 获取指定位置处的元素。
		String str3 = (String) list.get(list.size() - 1);
		// 返回此列表的最后一个元素。
		String str4 = (String) list.getLast();
		System.out.println(str3.equals(str4));

		// 获取但不移除此列表的头(第一个元素)。
		Object element = list.element();
		System.out.println(element);

		int size = list.size();
		System.out.println(size);
}

迭代

mport java.util.Iterator;
import java.util.LinkedList;

public class Demo3 {
	public static void main(String[] args) {
		LinkedList list = new LinkedList();
		list.add("西游记");
		list.add("三国演义");
		list.add("石头记");
		list.add("水浒传");
		list.add("全球通史");
		Iterator it = list.iterator();
		while (it.hasNext()) {
			String next = (String) it.next();
			System.out.println(next);
		}
	}
}

逆序迭代

import java.util.Iterator;
import java.util.LinkedList;

public class Demo6 {
	public static void main(String[] args) {
		LinkedList list = new LinkedList();
		list.add("aa");
		list.add("bb");
		list.add("cc");
		Iterator dit = list.descendingIterator();
		while (dit.hasNext()) {
			System.out.println(dit.next());
		}
	}
}

注意:可以使用该集合去模拟出队列(先进先出) 或者堆栈(后进先出) 数据结构。堆栈(后进先出)

//堆栈(后进先出) 数据结构
public class Demo3 {
	public static void main(String[] args) {
		LinkedList list = new LinkedList();
		// 压栈,先进后出
		list.push("西游记");
		list.push("三国演义");
		list.push("石头记");
		list.push("水浒传");
		System.out.println(list);
		// 弹栈
		String str1 = (String) list.pop();
		System.out.println(str1);
		String str2 = (String) list.pop();
		System.out.println(str2);
		String str3 = (String) list.pop();
		System.out.println(str3);
		String str4 = (String) list.pop();
		System.out.println(str4);
        System.out.println(list.size());// 0
		System.out.println(list); //[]
	}
}
 

队列,先进先出

import java.util.LinkedList;

public class Demo3 {
	public static void main(String[] args) {
		LinkedList list = new LinkedList();
		// 队列,先进先出
		list.offer("西游记");
		list.offer("三国演义");
		list.offer("石头记");
		list.offer("水浒传");
		System.out.println(list);
		// 出队列
		System.out.println(list.poll());
		System.out.println(list.poll());
		System.out.println(list.poll());
		System.out.println(list.poll());

		System.out.println(list.size());

		System.out.println(list.peek()); // 获取队列的头元素,但是不删除
		System.out.println(list.peekFirst()); // 获取队列的头元素,但是不删除
		System.out.println(list.peekLast()); // 获取队列的最后一个元素但是不删除

	}
}

8  Vector

Vector: 描述的是一个线程安全的ArrayList。       

 

ArrayList: 单线程效率高
Vector   : 多线程安全的,所以效率低

 

特有的方法:

 void addElement(E obj)  在集合末尾添加元素
 E elementAt( int index) 返回指定角标的元素
 Enumeration elements()  返回集合中的所有元素,封装到Enumeration对象中

 Enumeration 接口:
 boolean hasMoreElements() 
          测试此枚举是否包含更多的元素。 
 E nextElement() 
          如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。

public static void main(String[] args) 
	{
		Vector v = new Vector();
		v.addElement("aaa");
		v.addElement("bbb");
		v.addElement("ccc");
		System.out.println( v );
		System.out.println( v.elementAt(2) );   // ccc
		// 遍历Vector遍历
		Enumeration ens = v.elements();
		while ( ens.hasMoreElements() )
		{
			System.out.println( ens.nextElement() );
		}
	}

9 ArrayList 和 LinkedList

     ArrayList 的特点是采用数组实现。很类似于之前我们写的 MyList 类,当然,实际的
ArrayList 类和我们写的 MyList 相比,还是复杂了很多。

     用数组这样一种结构来实现 List 接口,具有以下特点:
     用数组实现 List 接口,如果要查询 List 中给定下标的元素,只需要使用数组下标就可以直接查到,实现起来非常方便,而且由于数组中,元素的存储空间是连续的,因此通过下标很容易快速对元素进行定位,因此查询效率也很高。
     但是,如果使用数组实现 List 接口,则必须要面对一个问题:数组的插入和删除的效率较低。例如,如果要进行数组的插入,有可能要大量移动数组的元素,有可能要进行数组的扩容从而进行大量的内存拷贝的工作。而数组的删除,同样可能意味着要移动大量的数组元素。因此,从这方面来说,数组的插入和删除操作效率比较低。
     而 LinkedList 实现 List 接口时,采用的是链表的实现方式。下面简单介绍一下链表这种数据结构。
     最基本的链表结构是这样的:链表由多个节点组成。每个节点分为两个部分:第一个部分用来储存链表的数据,另一个部分用来储存下一个节点的地址。如何来理解这个问题呢?
     我们可以用图来表示这种情况。例如,假设有如下代码:

List list = new LinkedList();
list.add("hello");
list.add("world");
list.add("java");
list.add("study");
上面的代码创建了一个 LinkedList,在内存中的图像如下:

 

     此时,如果调用 get(3)方法,则会由 hello 节点开始,先从 hello 节点找到 world 节点,再从 world 节点找到 java 节点,再从 java 节点找到 study 节点。因此在查询方面,相对于数组直接使用下标,链表实现的 LinkedList,在查询方面效率较低。
     而如果要进行插入操作,LinkedList 就会有比较明显的优势:因为 LinkedList 不需要进行数据内容的复制。
例如,假设运行了如下代码:
     list.add(1, “test”);
则内存中会进行下面的操作:
1. 创建一个新节点。如下图:


2. 修改 hello 和 test 的指针指向即可。如下图

 

 

 

     与之类似的,使用链表进行删除也只需要改动某个指针的指向即可。例如,假设运行了
如下代码:
     list.delete(2);
     则在内存中,完成的操作如下:

 

     由上面的例子可知,相对使用数组实现 List,使用链表实现 List 中的插入和删除功能,由于没有数组扩容以及移动数据等问题,因此效率要远远高于使用数组实现。

ArrayList 和 LinkedList 之间的区别如下表:

 

 

Vector 和 ArrayList 之间的比较如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值