java集合框架

集合概述:

          集合可以看作是一个容器,对于集合中的对象很容易将其存放到集合中,也很容易将其从集合中取出来,还可以将其按照一定的顺序进行摆放。Java中提供了不同的集合类,这些类具有不同的存储对象的方式,并提供了相应的方法以方便用户对集合进行遍历、添加、删除以及查找指定的对象。 提到容器不难想到数组,

                                         集合类与数组的不同之处是:1.数组的长度是固定的,集合的长度是可变的;

                                                                                        2.数组用来存放基本类型的数据,集合用来存放对象的引用;

                                                                                        3.数组的元素类型一致,集合元素类型可以不一致;

   常用的集合有List集合、Set集合、Map集合,其中ListSet实现了Collection接口。各接口还提供了不同的实现类。上述集合类的关系如下图所示:

  

Collection:定义了集合框架的共性功能。
(1)List(列表):元素是有序的,元素可以重复,因为该集合体系有索引。

                                  ArrayList:底层是数组数据结构,查询速度很快,但是增删稍慢,线程不同步,默认10个元素。(线程不同步)

                                  LinkedList:底层是链表数据结构,查询很慢,增删速度很快。(线程不同步)

(2)Set(集):元素是无序的(存入和取出顺序不一定一致),元素不可以重复。

                                  HashSet:底层数据结构是哈希表。线程是不同步的。

                                                   采用散列函数对元素进行排序Asiic),是专门为快速查询而设计的。存入HashSet的对象必须定义hashCode方法。

                                  LinkedHashSet:有序。

                                                    内部使用散列以加快查询速度,同时使用链表维护元素插入的次序,在使用迭代器遍历Set时,

                                                    结果会按元素插入的次序显示。 

                                TreeSet:底层的数据结构是二叉树。线程是不同步的。

          注意:集合只能保存引用数据类型,也就是存储的是对象的地址值,而不是对象本身。集合中的元素相当于引用类型变量。

package com.wyb.collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class CollectionOfList {
	public static void main(String[] args) {
		List<StringAddress> list = new ArrayList<StringAddress>(Collections.nCopies(4, new StringAddress("Hello")));
		System.out.println(list);
		Collections.fill(list, new StringAddress("World"));
		System.out.println(list);
		List<String> list1 = Arrays.asList(new String[] {"spring","summer","autumn","winter"});
		Collections.sort(list1);
		System.out.println(Collections.max(list1));
		System.out.println(Collections.min(list1));
		System.out.println(Collections.binarySearch(list1, "spring"));
		System.out.println(Arrays.toString(list1.toArray()));
		Collections.shuffle(list1);   //重新随即调整list中元素的位置1
		System.out.println(Arrays.toString(list1.toArray()));
	}

}
class StringAddress
{
	private String s;
	public StringAddress(String s)
	{
		this.s = s;
	}
	public String  toString()
	{
		return super.toString()+" "+s;
	}
}
Set :元素是无序的(存入和取出顺序不一定一致),元素不可以重复。

HashSet是如何保证元素唯一性的呢?

是通过两个方法,hashCode和equals来完成。

如果元素hashCode值相同,才会判断equals是否为true

如果元素的hashCode不同,不会调用equals方法。

怎么重写hashCode()和equals()方法呢?

hashCode():把对象的所有成员变量值相加即可。

如果是基本数据类型,就加值。如果是引用类型,就加哈希值。
return name.hasCode()+ age * 27;
equals(obj):先判断是否是同一类型的对象,再把传递进来的对象进行向下转型。再判断对象的内容是否相同。

if(!(obj instanceof Student)) ;

Student stu = (Student)obj; 

return this.name.equals(stu.name) && this.age == stu.age;

所有成员变量的值比较。基本类型用==,引用类型用equals()。

注意:对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法。


package com.wyb.collection;

import java.util.Collection;
import java.util.HashSet;

public class HashSetTest {
	/**
	 * HashSet类按照哈希算法来存取容器中的对象,具备很好的存取和查找性能。
	 * @param args
	 */
	public static void main(String[] args) {
		Collection<Object> c = new HashSet<Object>();
		c.add(new Person("Jack",20));
		c.add(new Person("Jack",20));
		System.out.println(c.size());
		System.out.println(c);
		c.add(new Integer(25));
		c.add("Hello World");
		System.out.println(c);
		c.remove(new Integer(25));
		c.remove("Hello World");
		System.out.println(c.remove(new Person("jack",20)));
		
	}

}
class Person
{
	private String name;
	private int age;
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public boolean equals(Object obj)  //重写equals方法
	{
		if(obj instanceof Person)  //实例化
		{
			Person p = (Person) obj;
			return (name.equals(p.name)) && (age==p.age);
		}
		return super.equals(obj);
	}
	public int hashCode() //重写hashCode方法
	{
		int i;
		i=(name==null?0:name.hashCode());//判断name是否为空
		i=10*i+age;
		return i;
	}
}

TreeSet :底层的数据结构是二叉树。线程是不同步的。


package com.wyb.collection;

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

public class ComputerComparator implements Comparator<Computer>{
	/**
	 * 实现Comparator接口,加入TreeSet容器中对向以brand降序排列,和place生序排列
	 */
	public static void main(String[] args) {
		Set<Computer> set = new TreeSet<Computer>(new ComputerComparator());
		set.add(new Computer("dell","shanghai"));
		set.add(new Computer("hp","shenzhen"));
		set.add(new Computer("hp","Guangzhou"));
		set.add(new Computer("lenovo","Beijing"));
		set.add(new Computer("dell","Beijing"));
		Iterator<Computer> it = set.iterator();
		while(it.hasNext())
		{
			Computer c = it.next();
			System.out.println(c);
		}
	}

	@Override
	public int compare(Computer c1, Computer c2) {
        if(c1.brand.compareTo(c2.brand)>0)   //brand降序
        	return -1;
        else if(c1.brand.compareTo(c2.brand)<0)
        	return 1;
        else
        	return c1.place.compareTo(c2.place);//place生序
		
	}

}
class Computer
{
	String brand;
	String place;
	public Computer(String brand, String place) {
		super();
		this.brand = brand;
		this.place = place;
	}
	@Override
	public String toString() {
		return "Computer [brand=" + brand + ", place=" + place + "]";
	}
	public boolean equals(Object obj)   //重写equals方法
	{
		if(!(obj instanceof Computer))
			return false;
		Computer c = (Computer) obj;
		if(this.brand.equals(c.brand) && this.place==c.brand)
			return true;
		else
			return false;
	}
	public int hashCode()  //重写hashCode方法
	{
		int result;
		result = (brand==null?0:brand.hashCode());
		return result;
	}
}
package com.wyb.collection;

import java.util.LinkedList;
//import java.util.Random;

public class LinkedListTest {
	/**
	 * LinkedList在内部是采用双向循环链表实现对,
	 * 插入与删除元素的速度较快,随即访问则较慢。
	 * LinkedList单独具有addFirst()、addLast()、getFirst()、getLast()
	 * removeFirst()和removeLast()方法
	 * @param args
	 */
	public static void main(String[] args) {
//		Random r = new Random(49);
		LinkedList<String> list = new LinkedList<String>();
		list.add(new String("rat"));
		list.add(new String("monkey"));
		list.add(new String("pig"));
		list.add(new String("rabbit"));
		System.out.println("list:"+list);
		System.out.println("list.getFirst:"+list.getFirst());
		System.out.println("list.element:"+list.element());
		System.out.println("list.peek:"+list.peek());
		System.out.println("list.remove:"+list.remove());
		System.out.println(list.removeFirst());
		System.out.println("poll:"+list.poll());
		System.out.println("list:"+list);
		list.addFirst(new String("mouse"));
		System.out.println("after addFirst:"+list);
		list.offer(new String("dog"));
		System.out.println(list);
		list.add(new String("rabbit"));
		System.out.println(list);
		list.addLast(new String("goat"));
		System.out.println(list);
		System.out.println(list.removeLast());
		System.out.println(list);
	}

}

Map<K,V>集合:该集合存储键值对。一对一往里存,而且要保证键的唯一性。

|--HashMap:基于哈希表的Map接口的实现。此实现提供所有可选的映射操作,并允许使用null 值和null键。

(除了非同步和允许使用null 之外,HashMap 类与Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。  Hashtable替代,JDK1.2.效率高。

 |--TreeMap:基于红黑树(Red-Black tree)的 NavigableMap 实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator(比较器) 进行排序,具体取决于使用的构造方法。 
和Set很像。其实大家,Set底层就是使用了Map集合。线程不同步。可以用于给Map集合中的键进行排序。

(1)Map是一个键值对形式的集合。它的元素都是由键和值组成。

(2)Map和Collection的区别?

A:Map 是由键值对组成的集合,Map的键是唯一的,值可以重复。

B:Collection 是有单列数据组成的集合,它的子类List是可以重复的,Set是唯一的。

(3)HashMap和Hashtable的区别?

HashMap:线程不安全,效率高。允许null键和值。

Hashtable:线程安全,效率低。不允许null键和值。

Map集合的两种取出方法

1. Set<k> keySet:将Map中所有的键存入到Set集合,因为Set具备迭代器。

    所以可以迭代方式取出所有的键,再根据get方法获取每个键对应的值

    Map集合取出原理:将Map集合转化成Set集合,再通过迭代器取出。

2.Set<Map.Entry<k,v>> entrySet:将Map集合中的映射关系存入到Set集合中,而这个关系的数据类型就是:Map.Entry

package com.wyb.collection;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class MapTest {
	/**
	 * 向容器中查询某一学生信息,如果存在则将该学生信息打印出来
	 * 并对容器中的5个学生信息依总学分的生序打印出来
	 * 
	 * 思路:
	 * 由于TreeMap容器中的值对象是student,需要一一取出它们,计算总学分,
	 * 再以总学分作为键对象放入到TreeMap容器中,值对象依然以student。
	 * TreeMap容器会自动以自然顺序对键值对进行排序
	 * @param args
	 */
	public static void main(String[] args) {
		TreeMap<Integer,Student> tm = new TreeMap<Integer,Student>();
		int total = 0;
		int[] grade = new int[5];
		Student[] s = new Student[5];
		tm.put(100001, new Student(100001, "王军", 85, 75, 95));
		tm.put(100002, new Student(100002, "小红", 90, 70, 80));
		tm.put(100003, new Student(100003, "小明", 92, 80, 80));
		tm.put(100004, new Student(100004, "旺财", 80, 87, 76));
		tm.put(100005, new Student(100005, "小强", 80, 70, 60));
		int[] arr = new int[5];
		int i = 0;
		int j = Integer.parseInt(args[0]);
		System.out.println("学号  姓名   计算机成绩  数学成绩  英语成绩  总分");
		if(tm.containsKey(j))
		{
			System.out.println("你要查找的学生信息是:");
			Student stu = tm.get(j);
			System.out.println(stu.id+"  ");
			System.out.println(stu.name+"  ");
			System.out.println(stu.computer_sore+"  ");
			System.out.println(stu.math_sore+"  ");
			System.out.println(stu.english_sore+"  ");
			total = stu.computer_sore+stu.math_sore+stu.english_sore;
			System.out.println(total);
		}
		System.out.println();
		TreeMap<Integer,Student> tp = new TreeMap<Integer,Student>();
		Iterator<Map.Entry<Integer, Student>> it = tm.entrySet().iterator();
		System.out.println("按总学分排序:");
		while(it.hasNext())
		{
			Map.Entry entry = it.next();
			arr[i] = (Integer) entry.getKey();
			s[i] = (Student) entry.getValue();
			System.out.print(s[i].id+"   ");
			System.out.print(s[i].name+"   ");
			System.out.print(s[i].computer_sore+"   ");
			System.out.print(s[i].math_sore+"   ");
			System.out.print(s[i].english_sore+"   ");
			total = s[i].computer_sore+s[i].english_sore+s[i].math_sore;
			System.out.println(total);
			System.out.println();
			grade[i]=total;
			tp.put(grade[i], s[i]);
			i++;
		}
		i=0;
		System.out.println("按总学分排序后:");
		Iterator<Map.Entry<Integer, Student>> iter = tp.entrySet().iterator();
		while(iter.hasNext())
		{
			Map.Entry entry1 = iter.next();
			arr[i] = (Integer) entry1.getKey();
			s[i] = (Student) entry1.getValue();
			System.out.print(s[i].id+"   ");
			System.out.print(s[i].name+"   ");
			System.out.print(s[i].computer_sore+"   ");
			System.out.print(s[i].math_sore+"   ");
			System.out.print(s[i].english_sore+"   ");
			total = s[i].computer_sore+s[i].english_sore+s[i].math_sore;
			System.out.println(total);
			System.out.println();
		}
	}

}
class Student
{
	int id;
	String name;
	int math_sore;
	int english_sore;
	int computer_sore;
	public Student(int id, String name, int math_sore, int english_sore,
			int computer_sore) {
		super();
		this.id = id;
		this.name = name;
		this.math_sore = math_sore;
		this.english_sore = english_sore;
		this.computer_sore = computer_sore;
	}
	
}

集合体系

Collection(单列)

List(有序,可重复)

ArrayList:  底层数据结构是数组,查询快,增删慢。线程不同步,效率高。  


LinkedList:底层数据结构是链表,查询慢,增删快。线程不同步,效率高。


Vector:      底层数据结构是数组,查询快,增删慢。线程同步,效率低。

Set(无序,唯一)

HashSet:底层数据结构是哈希表。线程不同步,效率高。 怎么保证唯一性的呢?它依赖两个方法:hashCode()和equals()顺序:首先判断hashCode()值是否相同。同:继续走equals(),看返回值如果true:就不添加到集合。如果false:就添加到集合。不同:就添加到集合。

TreeSet:底层数据结构是二叉树。 线程不同步,效率高。 怎么保证唯一性的呢?是根据返回是否是0。

怎么保证排序的呢?两种方式 

一、自然排序(元素具备比较性) 实现Comparable接口 

二、比较器排序(集合具备比较性) 实现Comparator接口

Map(双列 底层结构是针对键有效,跟值无关)

HashMap:底层数据结构是哈希表。线程不同步,效率高。

怎么保证唯一性的呢?

它依赖两个方法:hashCode()和equals()顺序:首先判断hashCode()值是否相同。同:继续走equals(),看返回值如果true:就不添加到集合。如果false:就添加到集合。不同:就添加到集合。


Hashtable:底层数据结构是哈希表。线程安全,效率低。

怎么保证唯一性的呢?

它依赖两个方法:hashCode()和equals()顺序:首先判断hashCode()值是否相同。同:继续走equals(),看返回值如果true:就不添加到集合。如果false:就添加到集合。不同:就添加到集合。


TreeMap:底层数据结构是二叉树。线程不同步,效率高。

怎么保证唯一性的呢?是根据返回是否是0。

怎么保证排序的呢?两种方式自然排序(元素具备比较性)实现Comparable接口比较器排序(集合具备比较性)实现Comparator接口

集合常见应用功能

(添加功能,判断功能,删除功能,获取功能,长度功能)



发布了32 篇原创文章 · 获赞 54 · 访问量 5万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章