可以简单理解为一个装东西的盒子或箱子,是用于存放元素的一种结构,包括变量,数组,对象,容器类详解见下文
Collection接口是所有容器的根层次接口,表示所有容器类的标准。
是否实现Collection接口是容器的判断条件。
public interface Set<E> extends Collection<E>
基本数据类型不能当作泛型来使用,需要使用基本数据类型的封装类
set的特点:不能存在重复的元素(hashcode相同的元素为重复元素)
public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, Serializable
hs.add(E o);/*添加元素*/ (boolean)
hs.clear();/*移除所有元素*/ (void)
hs.clone();/*浅表复制,并没有克隆*/ (object)
hs.contains(Object o);/*不包含o元素时返回true*/ (boolean)
hs.isEmpty();/*没有元素时返回true*/ (boolean)
hs.iterator();/*返回迭代器*/ (iterator<E>)
hs.remove(Object o);/*移除o元素*/ (boolean)
hs.size();/*返回容量长度*/ (int)
hs.contains(Object o);//不包含o元素时返回true (boolean)
package com.sjh.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class HashSetTest1 {
public static void main(String[] args) {
Set<String> hs = new HashSet<String>();
//添加元素
hs.add("123");
hs.add("456");
hs.add("qaa");
hs.add("xxx");
hs.add("123");//不生效
hs.add(null);
//获取
//for-each循环
System.out.println("for-each循环");
for(String sbrt : hs){
System.out.println(sbrt);
}
//或者使用迭代器
System.out.println("迭代器");
Iterator<String> it = hs.iterator();
while(it.hasNext()){
String str = it.next();
System.out.println(str);
}
//remove移除
hs.remove("123");
System.out.println(hs);
}
}
输出结果
for-each循环
qaa
null
123
456
xxx
迭代器
qaa
null
123
456
xxx
[qaa, null, 456, xxx]
1.不能存放重复元素
2.底层代码结构是哈希表(HashTable)
3.无序----无索引
4.可以存放null元素
5.牺牲空间换时间(桶)----运行速度较快
6.初始容量16和加载因子0.75,根据底层hashMap实例决定
7.实现不同步,线程不安全
String score[] s ={
“A,语文,98”,
“B,数学,87”,
“B,英语,56”,
“C,语文,66”,
“G,数学,90”};
name[A B C D E F G]
问:谁没有参加考试
package com.sjh.Set;
import java.util.HashSet;
import java.util.Set;
public class HashSetTest2 {
public static void main(String[] args) {
String[] score={
"A,语文,98",
"B,数学,87",
"B,英语,56",
"C,语文,66",
"G,数学,90"};
String[] name={"A","B","C","D","E","F","G"};
Set<String> scoreSet=new HashSet<String>();
for (int i = 0; i < score.length; i++) {
//以逗号为界拆分score并暂时存放在bRet中
//bRet[0]=A,bRet[1]=语文,bRet[2]=98
String[] bRet = score[i].split(",");
//把bRet[0]添加到scoreSet中
scoreSet.add(bRet[0]);
}
System.out.println(scoreSet);
Set<String> nameSet=new HashSet<String>();
for (int i = 0; i < name.length; i++) {
nameSet.add(name[i]);
}
System.out.println(nameSet);
//数学差集
nameSet.removeAll(scoreSet);
System.out.println(nameSet);
}
}
输出结果
[A, B, C, G]
[A, B, C, D, E, F, G]
[D, E, F]
问:HashSet是否是HashMap的实例?
答:是,虽然两个容器实现的是不同的接口,但是底层都是哈希表(HashTable)
问:什么是重复元素?
重复元素的哈希值(hashcode)一定相同,一定在同一个桶内
哈希值(hashcode)相同的元素不一定是重复元素,桶内不只有一个类,还需要使用equals(java.lang.Object)方法确定
ts.add(E o);/*添加元素*/ (boolean)
ts.clear();/*移除所有元素*/ (void)
ts.clone();/*浅表复制,并没有克隆*/ (object)
ts.contains(Object o);/*包含o元素时返回true*/ (boolean)
ts.isEmpty();/*没有元素时返回true*/ (boolean)
ts.iterator();/*返回迭代器*/ (iterator<E>)
ts.remove(Object o);/*移除o元素*/ (boolean)
ts.size();/*返回容量长度*/ (int)
ts.contains(Object o);//包含o元素时返回true (boolean)
ts.first();/*返回已排序set中第一个(最小)元素*/ (E)
ts.last();/*返回已排序set中最后一个(最大)元素*/ (E)
//返回用于确定已排序set顺序的比较器,或者,如果此树set使用其元素的自然顺序,则返回 null
ts.comparator(); (Comparator<? super E>)
//返回此set的部分视图,要求其元素严格小于 toElement
ts.headSet(E toElement); (SortedSet<E>)
//返回此set的部分视图,其元素从fromElement(包括)到toElement(不包括)
ts.subSet(E fromElement, E toElement); (SortedSet<E>)
//返回set的部分视图,其元素大于或等于fromElement
ts.tailSet(E fromElement); (SortedSet<E>)
package com.sjh.Set;
import java.util.Set;
import java.util.TreeSet;
import java.util.Iterator;
public class TreeSetTest1 {
public static void main(String[] args) {
Set<Integer> ts = new TreeSet<Integer>();
ts.add(7);
ts.add(0);
ts.add(2);
ts.add(3);
ts.add(0);//不生效
//ts.add(null);//不能存放null,报java.lang.NullPointerException异常
//获取
//for-each循环
for(Integer sbrt : ts){
System.out.println(sbrt);
}
//或者使用迭代器
Iterator<Integer> it = ts.iterator();
while(it.hasNext()){
Integer str = it.next();
System.out.println(str);
}
//remove移除
ts.remove(0);
System.out.println(ts);
}
}
输出结果
for-each循环
0
2
3
7
迭代器
0
2
3
7
[2, 3, 7]
1.不能存放重复元素
2.底层结构是二叉树结构
3.二叉树认为能够存放在树形结构中的元素都是有序元素
4.实现不同步,线程不安全
问:HashSet和TreeSet的异同?
同:不能存放重复元素,实现不同步,线程不安全
HashSet底层代码结构是哈希表(HashTable),无序,可以存放null
TreeSet底层代码结构是二叉树,有序,不能存放null
实体类实现Comparable接口 ,该实体类就存在自然排序的功能
package com.sjh.Set;
public class Person implements Comparable<Object>{
private String name;
private int age;
//构造方法
public Person() {
// TODO Auto-generated constructor stub
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
//get和set方法
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//重写toString方法
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
@Override//重写compareTo方法
public int compareTo(Object o) {
//instanceof------检查Object o是否是Person类型
if (!(o instanceof Person))
return -1;
Person p = (Person) o;//强制转换
return this.getName().compareTo(p.getName());
}
}
//根据元素的自然顺序 对指定列表按升序进行排序
Collections.sort(List<T> list) (static <T extends Comparable<? super T>> void)
//根据指定比较器产生的顺序对指定列表进行排序
Collections.sort(List<T> list, Comparator<? super T> c) (static <T> void )
package com.sjh.Set;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class TreeSetTest2 {
public static void main(String[] args) {
List<Person> set = new ArrayList<Person>();
set.add(new Person("zhangsan",18));
set.add(new Person("lisi",27));
set.add(new Person("wangwu",21));
//Comparable自然排序
Collections.sort(set);
System.out.println(set);
//Comparator自定义排序
Collections.sort(set, new Comparator<Person>(){
@Override//重写compare方法
public int compare(Person o1, Person o2) {
return o1.getAge()-o2.getAge();//小于返回-1,等于返回0,大于返回1
}
}
);
System.out.println(set);
}
}
输出结果
[Person [name=lisi, age=27], Person [name=wangwu, age=21], Person [name=zhangsan, age=18]]
[Person [name=zhangsan, age=18], Person [name=wangwu, age=21], Person [name=lisi, age=27]]
问:Collection和Collections的区别?
Collection是容器类的根接口,用于描述一个类是否是容器,里面实现了增删改查方法
Collections是Collection的工具类,主要用于集合的排序,反转,线程安全等
问:Comparable和Comparator的异同?
同:小于返回负整数,等于返回0,大于返回正整数
public interface Comparable
public interface Comparator
package com.sjh.CustomBinaryTree;
public class Node {
public int data; //数据
public Node leftNode; //左节点
public Node rightNode; //右节点
/**
* 添加节点
* @param t
*/
public void addNode(Node p){ //p为包括1个根节点,1个左节点和1个右节点在内的一个二叉树
//data是p这个树的根节点的值
if(p.data<this.data){ //比根节点小,p嫁接在根树左节点上
if(leftNode == null) //左节点为空时,p成为左节点
leftNode = p;
else
leftNode.addNode(p); //把左节点作为根节点添加节点,递归循环
}else{ //比根节点大,p嫁接在根树右节点上
if(rightNode == null) //右节点为空时,p成为右节点
rightNode = p;
else
rightNode.addNode(p); //把右节点作为根节点添加节点,递归循环
}
}
/**前序递归遍历
* Preorder Recursion Traversal (VLR)
*/
public void VLRrSort(){
System.out.print(data+" ");
if(leftNode!=null) leftNode.VLRrSort();
if(rightNode!=null) rightNode.VLRrSort();
}
/**中序递归遍历
* Inorder Recursion Traversal (LDR)
*/
public void LDRrSort(){
if(leftNode!=null) leftNode.LDRrSort();
System.out.print(data+" ");
if(rightNode!=null) rightNode.LDRrSort();
}
/**后序递归遍历
* Postorder Recursion Traversal (LRD)
*/
public void LRDrSort(){
if(leftNode!=null) leftNode.LRDrSort();
if(rightNode!=null) rightNode.LRDrSort();
System.out.print(data+" ");
}
}
package com.sjh.CustomBinaryTree;
public class MyTree {
private Node rootNode;
public void add(int x){
Node p = new Node();
p.data = x;
if(rootNode == null){
rootNode = p;
}else
rootNode.addNode(p);
}
public void VLRrSort(){
if(rootNode==null)
return ;
else{
rootNode.VLRrSort();
System.out.println();
}
}
public void LDRrSort(){
if(rootNode==null)
return ;
else{
rootNode.LDRrSort();
System.out.println();
}
}
public void LRDrSort(){
if(rootNode==null)
return ;
else{
rootNode.LRDrSort();
System.out.println();
}
}
}
package com.sjh.CustomBinaryTree;
public class MyTreeTest {
public static void main(String[] args) {
MyTree my = new MyTree();
my.add(5);
my.add(2);
my.add(4);
my.add(3);
my.add(6);
my.add(1);
my.add(9);
my.add(5);
my.VLRrSort();//前序递归,根左右
my.LDRrSort();//中序递归,左根右
my.LRDrSort();//后序递归,左右根
}
}
输出结果
5 2 1 4 3 6 5 9
1 2 3 4 5 5 6 9
1 3 4 2 5 9 6 5
List的特点:可以存在重复的元素,存储顺序有序,可以在任何位置上插入元素,更利于做元素的查找
特点:底层代码结构是动态数组,线程安全,1.2JDK版本,默认容量10
不建议使用的原因:已被淘汰
1.线程安全导致效率低,与StringBuffer类似,有更好的实现线程安全的替代方法
2.只能在尾部进行插入和删除操作,效率低
3.分配内存时需要连续的存储空间,如果数据太多,容易分配内存失败
4.Vector扩容是一倍,ArrayList扩容只需一半
5.JDK向下兼容但不建议使用旧版本的JDK
al.add(E o);/*添加元素到末尾*/ (boolean)
al.add(int index, E element);在index处插入element (void)
al.clear();/*移除所有元素*/ (void)
al.clone();/*返回一个副本,复制*/ (object)
al.contains(Object elem);/*包含elem元素时返回true*/ (boolean)
al.get(int index);/*返回指定位置index处的元素*/ (E)
al.isEmpty();/*没有元素时返回true*/ (boolean)
al.remove(int index);/*移除索引index处的元素*/ (E)
al.remove(Object o);/*移除o元素的单个实例,只移除一个*/ (boolean)
//用element替代index处的元素,并返回原来index处的元素
al.set(int index,E element); (E)
al.size();/*返回列表长度*/ (int)
//如有必要,增加ArrayList实例的容量,指定容量为minCapacity
//以确保它至少能够容纳最小容量参数(minCapacity)所指定的元素数
al.ensureCapacity(int minCapacity); (void)
//返回elem第一次出现的索引位置,使用equals方法进行相等性测试,未找到返回-1
al.indexOf(Object elem); (int)
//返回elem最后一次出现的索引位置,使用equals方法进行相等性测试,未找到返回-1
al.lastIndexOf(Object elem); (int)
//移除索引在fromIndex(包括)和toIndex(不包括)之间的所有元素
al.removeRange(int fromIndex, int toIndex); (protected void)
//返回一个按照正确的顺序包含此列表中所有元素的数组,对象数组为Object一般不用
al.toArray(); (Object[])
//返回一个按照正确的顺序包含此列表中所有元素的数组
//指定数组是什么类型,返回的就是数组就是什么类型
al.toArray(T[] a); (<T> T[])
//将此ArrayList实例的容量调整为列表的当前大小,主要用于最小化实例的存储量
al.trimToSize(); (void)
//将指定Collection中的所有元素追加到此向量的末尾,按照指定集合的迭代器所返回的顺序追加这些元素
al.addAll(Collection<? extends E> c); (boolean)
//在index处将指定Collection中的所有元素插入到此向量中
al.addAll(int index, Collection<? extends E> c); (boolean)
//将指定的组件添加到此向量的末尾,将其大小增加1
al.addElement(E obj); (void)
package com.sjh.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArrayListTest1 {
public static void main(String[] args) {
String[] a1 = new String[8];
String[] a2 = new String[7];
String[] a3 = new String[6];
String[] a4 = new String[5];
String[] a5 = new String[4];
List<String> list = new ArrayList<String>();
list.add("3");
list.add("2");
list.add("4");
list.add("6");
list.add("3");
list.add("6");
String s = list.set(3,"1");
list.toArray(a1);
list.toArray(a2);
list.toArray(a3);
list.toArray(a4);
list.toArray(a5);
System.out.println(s);//返回索引3处原来的元素6
System.out.println(Arrays.toString(a1));//长度超出后面补null
System.out.println(Arrays.toString(a2));
System.out.println(Arrays.toString(a3));//尽量保持长度一致
System.out.println(Arrays.toString(a4));
System.out.println(Arrays.toString(a5));//长度不足放不进去,全是null
}
}
输出结果
6
[3, 2, 4, 1, 3, 6, null, null]
[3, 2, 4, 1, 3, 6, null]
[3, 2, 4, 1, 3, 6]
[null, null, null, null, null]
[null, null, null, null]
1.代码底层结构是动态数组
2.线程不同步,线程不安全
3.更擅长做随机访问-遍历
4.添加元素和删除元素的方法,运行速度比LinkedList慢
与ArrayList相同
1.代码底层结构是链表
2.有序—有索引
3.线程不同步,线程不安全
4.实现了队列Queue,说明它是个队列 FIFO(先进先出),LIFO(后进先出)
5.堆栈的实现,队列的实现,以及双端队列的实现
6.LinkedList更擅长做添加和修改以及删除等操作,运行速度要比ArrayList快
Element
Offer
Poll
Peek
Remove
来自于队列的接口
ArrayList和LinkedList各自的使用场合
1.随机访问------遍历------ArrayList
2.插入删除操作较多时------LinkedList
3.线程不安全队列结构------LinkedList
4.线程不安全动态数组------ArrayList
package com.sjh.List;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class TelNote {
private Set<List<Person>> set = null;
private List<Person> list = null;
public TelNote() {
set = new HashSet<List<Person>>();
}
/**
* 添加元素
* @param p
*/
public void add(Person p){
if(list == null){
list = new ArrayList<Person>();
}
list.add(p);
set.add(list);
}
/**
* 查找人
* @return
*/
public Person getPerson(String name){
Iterator<List<Person>> it = set.iterator();
while(it.hasNext()){
List<Person> persons = it.next();
for(Person p :persons){
if(p.getName().equals(name)){
return p;
}
}
}
return null;
}
}
package com.sjh.List;
public class Test1 {
public static void main(String[] args) {
TelNote tel = new TelNote();
for (int i = 0; i < 5; i++) {
tel.add(new Person("zhangsanfeng"+i, 99+i));
}
Person p = tel.getPerson("zhangsanfeng1");
System.out.println(p);
}
}
package com.sjh.List;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
public class ListTest {
public static void main(String[] args) {
LinkedList<String> list = new LinkedList<String>();
list.add("123");
list.add("345");
list.add("1098");
list.add("uuu");
list.add("ooo");
list.addFirst("123");
list.addLast("999");
String key = list.element();
System.out.println(list);
System.out.println(key);
list.getFirst();
System.out.println(list);
list.offer(null);
String result = list.peek();
System.out.println(result);
String result1 = list.poll();
System.out.println(list);
Stack<String> s = new Stack<String>();
s.push("123");
s.push("456");
s.push("90099");
s.push("163");
s.push("1200");
System.out.println(s);
String bRet = s.pop();
System.out.println(bRet);
}
}