集合概述:
集合可以看作是一个容器,对于集合中的对象很容易将其存放到集合中,也很容易将其从集合中取出来,还可以将其按照一定的顺序进行摆放。Java中提供了不同的集合类,这些类具有不同的存储对象的方式,并提供了相应的方法以方便用户对集合进行遍历、添加、删除以及查找指定的对象。 提到容器不难想到数组,
集合类与数组的不同之处是:1.数组的长度是固定的,集合的长度是可变的;
2.数组用来存放基本类型的数据,集合用来存放对象的引用;
3.数组的元素类型一致,集合元素类型可以不一致;
常用的集合有List集合、Set集合、Map集合,其中List与Set实现了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来完成。
如果元素hashCode值相同,才会判断equals是否为true。
如果元素的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(有序,可重复)
Set(无序,唯一)ArrayList: 底层数据结构是数组,查询快,增删慢。线程不同步,效率高。
LinkedList:底层数据结构是链表,查询慢,增删快。线程不同步,效率高。
Vector: 底层数据结构是数组,查询快,增删慢。线程同步,效率低。
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接口
集合常见应用功能
(添加功能,判断功能,删除功能,获取功能,长度功能)