13、集合1
一、概念
集合是程序设计中的一种基本实现。在java中包含数组的概念,但是一维数组有一个固定的概念,所以数组在处理那些随着应用程序的运行而增长或缩减的对象时非常笨拙
所有的集合父类是一个Collection接口,该接口也定义了一些基本操作;
集合优点:可以自由增加缩减大小;缺点:速度慢
二、迭代器iterator接口
用于遍历Collection集合中的元素,主要方法有以下三个:
boolean hasNext():如果被迭代的集合元素还没有被遍历,则返回true
Object next():返回集合里的下一个元素
void remove():删除集合里上一个next()方法返回的元素
三、list列表
1、数组列表:
初始化:List list=new ArrayList();
可以代替数组,可以自行增加减少大小。常用方法:
add():增加Object,一次一个,任何种类都可以
remove():移除对象,分两种,一种参数为对象,一种参数为索引,按情况来使用
----然而当使用index参数时候,容易出现数组索引越界的异常,解决方法:将基本变量包装类化,然后再在remove中使用该包装类
indexOf(Object obj):返回位置对象的索引
isEmpty():是否为空
clear():清空
get(int index):得到某个位置的object
itervator():将列表中的对象放到迭代器中,返回一个迭代器
Itervator it=list.itervator();
toArray():转化成数组,返回为Object类型的数组。
遍历方法:
a、使用foreach:foreach时候类型为Object;
b、使用常用的for语句:i<list.size();输出list.get();
c、使用迭代器:使用while(it.hasNext){sout(it.next());}
Iterator it=list.iterator(); while(it.hasNext()){ System.out.println(it.next()); }
d、使用ListIterator(),是Iterator的子类,可以从后往前或从前往后两种遍历
ListIterator lit=list.listIterator(); while(lit.hasNext()){ System.out.println(lit.next()); } while(lit.hasPrevious()){ System.out.println(lit.previous()); }
e、使用toArray()方法,让列表转化为数组之后再逐个输出。
Object []obj=list.toArray(); for(int i=0;i<obj.length;i++){ System.out.println(obj[i]); }
2、Vector的用法
vector:矢量;
与Arraylist的区别:Vector在开发过程中使用一个线程,线程同步,能够确保线程安全,避免线程竞技;速度慢;
List:所有方法都是非同步的,不安全,多线程访问同一个ArrayList对象时,需要自己处理线程同步问题。速度快;
当只有一个线程或多线程访问时能确保线程安全,使用ArrayList比使用Vector效率高
初始化:Vector<String> list=new Vector();
比ArrayList多出来的方法:list.addElement()
比ArrayList多出来的遍历方法
在Vector中最好用这个
Enumeration<String> enums=list.elements();
while(enums.hasMoreElements()){
enums.nextElement();
}
四、泛型
使用泛型机制可以避免使用杂乱的Object变量,使类型转换的diamante具有更好的安全性和可读性,泛型对于集合来说尤为重要
泛型和C++语言中的模板很相似。使用泛型意味着编写的代码可以被很多不同的类型所重用。
例子:使用的是数组列表:
package com.zxc.M; import org.junit.Test; import java.util.*; /** * Created by Administrator on 2018/2/7 0007. */ public class A { @Test public void test(){ List<String> list=new ArrayList(); list.add("a"); list.add("100"); list.add(new Date().toString()); for(String obj:list){ System.out.println(obj); } for(int i=0;i<list.size();i++){ System.out.println(list.get(i)); } Iterator<String> it=list.iterator(); while(it.hasNext()){ System.out.println(it.next()); } ListIterator<String> lit=list.listIterator(); while(lit.hasNext()){ System.out.println(lit.next()); } while(lit.hasPrevious()){ System.out.println(lit.previous()); } Object []obj=list.toArray(); for(int i=0;i<obj.length;i++){ System.out.println(obj[i]); } } }
泛型中定义的具体类型不能是基本类型,必须用包装类。
public class B { public static void main(String[] args) { Animal<String> a=new Animal(); a.setGrade("一年级"); System.out.println(a.getGrade()); Animal<Integer> a1=new Animal(); a1.setGrade(1); System.out.println(a1.getGrade()); } } class Animal<T>{ private T grade; public T getGrade() { return grade; } public void setGrade(T grade) { this.grade = grade; } }
五、购物车项目(内存版)
购物车的含义是如果添加的是同类商品,那么使其商品数量加一,否则添加一种新商品。(使用商品编号来看是否为同一种商品)
商品类(Goods类)
public class Goods implements Serializable{ private String no; private String name; private float price; private int quantity; public Goods(String no, String name, float price, int quantity) { this.no = no; this.name = name; this.price = price; this.quantity = quantity; } public String getNo() { return no; } public void setNo(String no) { this.no = no; } public String getName() { return name; } public void setName(String name) { this.name = name; } public float getPrice() { return price; } public void setPrice(float price) { this.price = price; } public int getQuantity() { return quantity; } public void setQuantity(int quantity) { this.quantity = quantity; } }
购物车类(Cart类)
import java.util.ArrayList; import java.util.List; /** * Created by Administrator on 2018/2/7 0007. */ public class Cart { private Cart(){ } private static List<Goods> list=new ArrayList(); public static List<Goods> getList() { return list; } }
测试类(Test类)
import java.util.List; /** * Created by Administrator on 2018/2/7 0007. */ public class Test { public List buy(Goods ngoods){ List<Goods> list=Cart.getList(); boolean flag=false; for(int i=0;i<list.size();i++){ Goods ogoods=list.get(i); if(ngoods.getNo().equals(ogoods.getNo())){ ogoods.setQuantity(ogoods.getQuantity()+ngoods.getQuantity()); flag=true; break; } } if(flag==false){ list.add(ngoods); } return list; } public static void main(String[] args) { Test test=new Test(); test.buy(new Goods("001","honey",10.2f,5)); test.buy(new Goods("001","honey",10.2f,2)); test.buy(new Goods("002","sweets",2.5f,6)); List<Goods> list=test.buy(new Goods("003","water",1.4f,7)); for(Goods goods:list){ System.out.println(goods.getNo()+"-"+goods.getName()+"-"+goods.getPrice()+"-"+goods.getQuantity()); } } }
六、Queue接口 -实现类:LinkedList
该接口扩展了java.util.Collection接口,支持队列操作。
除了基本的Collection操作外,队列还提供了其他的插入、提取、和检查操作。
每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(null或false,具体取决于操作)
实现Queue接口的类是LinkedList,其中既有list列表的方法,又有Queue队列的方法。
ArrayList、Vector、LinkedList区别:(前两个只实现了链表,否则实现了链表的同时还实现了队列)
LinkedList与ArrayList、Vector实现的机制完全不同,ArrayList、Vector内部以数组的形式来保存集合中的元素,因此在随机访问集合元素上有较好的性能;而LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合元素时性能较差,但在插入、删除元素时性能非常出色。
常用方法:
插入:add(e) 插入到末尾 包括:addFirst() addLast()
增加:offer() 包括offerFirst() offerLast()等同于add()
移除:remove(index)
删除堆:poll() 删除头部 pollFirst() pollLast()
显示: peek()从头显示第一个 peekFirst()从头显示第一个 peekLast()从尾显示最后一个
模仿压栈:push()在链表最顶部压入数据
模仿出栈:pop()在链表最顶部弹出数据
七、Deque接口
继承了Deque(双向队列)接口,使用此类可以自己实现实现java.util.Stack类的功能,去掉了java.util.Stack的多线程同步功能,DQueue接口的类为ArrayDeque。
用Deque手工模拟做栈
public class E { public static void main(String[] args) { E1 e1=new E1(); for(int i=0;i<10;i++){ e1.push(i); } System.out.println(e1.pop()); System.out.println(e1.peek()); } } class E1{ private Deque<Integer> deque=new ArrayDeque(); public void push(Integer i){ deque.add(i); } public Integer pop(){ return deque.removeLast(); } public Integer peek(){ return deque.peekLast(); } }
八、HashTable类和HashMap类
HashTable类初始化:Hashtable<Integer,String> t=new Hashtable();
常用方法:
put():添加键值对
查看键(hashtable独有方法):
Enumeration<Integer> enums1=t.keys(); while(enums1.hasMoreElements()){ System.out.println(enums1.nextElement()); }
查看值(hashtable独有方法):
Enumeration<String> enums=t.elements(); while(enums.hasMoreElements()){ System.out.println(enums.nextElement()); }
查看键值对:
Set<Map.Entry<Integer,String>> ss= t.entrySet(); for (Map.Entry<Integer,String> e:ss){ System.out.println(e); }
多少个元素:size()
hashmap:
查看键(hashtable也可以用):
Set<Integer> s=t.keySet(); for(Integer i:s){ System.out.println(i); }
查看值(hashtable也可以用):
Collection<String> si=t.values(); for(String sii:si){ System.out.println(sii); } }
hashmap和hashtable区别:
1、Hashtable继承了Dictionary类,Hashmap是Map接口的一个实现类,继承自AbstractMap抽象类。
2、在HashMap中,null可以作为键,这样的键只能有一个:可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断,而在Hashtable中不允许有null键和null值。
3、HashTable为线程同步,安全,速度慢;HashMap为线程不同步,不安全速度快。
4、两者的遍历方法大同小异,Hashtable仅仅比HashMap多一个elements方法
5、两者也都可以通过entrySet()方法返回一个Set,然后进行遍历处理。HashTable使用Enumeration,HashMap使用Iterator。
6、哈希值使用不同,Hashtable直接使用对象的hashCode。而HashMap需要重新计算hash值,而且用于代替求模;
7、hashtable中hash数组的默认大小是11,增加的方式使old*2+1。hashmap中hash数组默认大小为16,而且一定是2的指数