数组和集合同为容器,区别?
1、数组虽然可以存储对象,但长度固定,集合长度是可变的。
2、数组中可以存储基本数据类型,集合只能存储对象。
集合类的特点:集合只用于存储对象,长度可变,能存储不同类型的对象。
集合框架:
每一个容器对数据的存储方式都有不同
共性方法:
添加:add(): add方法的参数类型的Object,以便于接收任意类型对象。集合中存储的都是对象的引用(或地址)
addAll()
删除:remove()
clear(); //清空集合
判断:contains(Object o)
equals()
isEmpty()
retainAll(): 取交集,a1.retainAll(a2)返回a1中只包含a2的元素。
removeAll(): 删除交集
hashCode()
1、迭代器:
List<String> ll=new LinkedList<String>();
ll.add("first");
for(Iterator<String> iter = ll.iterator();iter.hasNext;){
String str=(String)iter.next();
System.out.println(str);
}
2、set、List和map区别
set: 元素不能重复(定义equals方法确保对象的唯一性),无序
list:有序,按对象进入的顺序保存对象,可以重复,Array List、Vector、Linked List都实现了list接口。
特有方法:可以操作角标的方法
增:add(index,ele);
addAll(index,Collection);
删:remove(index)
改:set(index,ele)
查:get(index)
subList(from,to)
ListIterator(); //继承自Iterator,功能丰富
在迭代时,不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常。所以,在迭代时,只能用迭代器的方法操作元素,可是Iterator方法有限,只能对元素进行判断,取出,删除的擦欧总,如果想要其他操作,如添加add,修改set等,需要使用其子接口ListIterator()
ListIterator li = ll.listIterator();
while(li.hasNext()){
Object obj=li.next();
if(obj.equals(" "))
li.set(" ");
}
1)Array List: 底层数据结构是数组
特点:查询速度块,增删效率低,线程不同步
练习:
Test1、去除ArrayList中重复的元素
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListTest {
public static void main(String[] args){
ArrayList array = new ArrayList();
array.add("01");
array.add("02");
array.add("03");
array.add("02");
array.add("04");
System.out.println(delDup(array));
}
public static ArrayList delDup(ArrayList arr){
//定义一个临时容器
ArrayList arr_ = new ArrayList();
Iterator it = arr.iterator();
while (it.hasNext()){
Object obj = it.next();
if(!arr_.contains(obj)){
arr_.add(obj);
}
}
return arr_;
}
}
Test2、将自定义对象存储在ArrayList中,去除重复的元素
import java.util.ArrayList;
import java.util.Iterator;
class Person{
private String name;
private int age;
Person(String name,int age){
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
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;
}
}
public class ArrayListTest {
public static void main(String[] args){
ArrayList array = new ArrayList();
array.add(new Person("zhangsan",20));
array.add(new Person("zhangsan",20));
array.add(new Person("lisi",20));
array.add(new Person("limeng",30));
array=delDup(array);
Iterator it = array.iterator();
while (it.hasNext()){
Person p = (Person)it.next();
System.out.println(p.getName()+","+p.getAge());
}
}
public static ArrayList delDup(ArrayList arr){
//定义一个临时容器
ArrayList arr_ = new ArrayList();
Iterator it = arr.iterator();
while (it.hasNext()){
Object obj = it.next();
if(!arr_.contains(obj)){ //contains底层原理是equals
arr_.add(obj);
}
}
return arr_;
}
}
list集合判断元素是否相同,依据元素的equals方法。
2)Linked List: 底层数据结构是链表
特点:增删速度快,查询效率低
addFirst("01");
addFirst("02"); //02 01逆序输出
addLast("01");
addLast("02");//正序输出
getFirst(): 01
getLast(): 02
removeFirst(); 取出元素,且删除了该元素
练习:
Test3、使用LinkedList模拟一个堆栈或队列数据结构
堆栈:先进后出
队列:先进先出
import java.util.LinkedList;
class MyQueue{
private LinkedList list;
MyQueue(){
list = new LinkedList();
}
public void add(Object obj){
list.addFirst(obj);
}
public Object get(){
//return list.removeLast(); //队列
return list.removeFirst(); //栈
}
public boolean isNull(){
return list.isEmpty();
}
}
public class LinkedListTest {
public static void main(String[] args){
MyQueue q = new MyQueue();
q.add("01");
q.add("02");
q.add("03");
q.add("04");
while(!q.isNull()){
System.out.println(q.get());
}
}
}
3)Vector: 底层数据结构是数组
特点:线程同步,效率低,
引申:Array List、Vector、Linked List区别
同:均为可伸缩数组,即可以动态改变长度的数组
异:
Array List、Vector都是基于数组实现,会在内存中开辟一块连续的空间来存储,所以支持用下标访问元素,索引数据速度块,但插入元素需要移动容器中元素,所以效率低。Array List、Vector都有一个初始化的容量大小10,当元素超过时要动态扩容,Array List默认扩为原来的1.5倍,Vector默认扩为原来的2倍。两者最大区别是同步,Vector是线程安全的,性能略低。
Linked List基于链表实现,对数据的索引需要从列表头开始遍历,随机访问效率低,但插入元素不需要移动,非线程安全。
适用场景:
当对数据的组要操作为索引或只在集合的末端增加删除元素时,使用Array List、Vector效率较高,
当对数据的组要操作为指定为止的插入或删除时,Linked List
当在多线程中,vector
泛型:
Map<K,V>:保存键值对,值可以重复,但键是唯一的,不能重复
添加:
put(key,value):添加元素,如果添加相同的键,新值会覆盖旧值,返回旧值。
putAll()
删除:
clear()
remove(Object key)
获取:
get(Object key):键对应的值
values():获取集合中所有的值。
Set<k> keySet():将map中所有的键存入到Set集合,因为Set具备迭代器,所以可以通过迭代取出所有的键,再通过get(key)方法获取每个键对应的值。
Set<Map.Entry<k,v>> entrySet():将map集合中的映射关系存入到set集合中,而这个关系的数据类型就是:Map.Entry。
接口 Map.Entry<k,v> 其实,Entry也是一个接口,它是Map接口中的一个内部接口。
interface Map{
public static interface Entry{
public abstract Object getKey();
public abstract Object getValue();
}
}
class HashMap implements Map{
class implements Map.Entry
public Object getKey(){}
public Object getValue(){}
}
判断:
containsKey(key)
containsValue(value)
isEmpty()
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapTest {
public static void main(String[] args){
Map<String ,String> map = new HashMap<String, String>();
map.put("01","karry");
map.put("02","windy");
map.put("03","jane");
Set<Map.Entry<String,String>> entrySet = map.entrySet();
Iterator<Map.Entry<String,String>> it = entrySet.iterator();
while (it.hasNext()){
Map.Entry<String,String> me=it.next();
String key=me.getKey();
String value=me.getValue();
System.out.println("key:"+key+",value:"+value);
}
//System.out.println(map.containsKey("01"));
//System.out.println(map.remove("01"));
//System.out.println(map.get("01"));
//System.out.println(map);
//System.out.println(map.values());
//System.out.println(map.put("01","ka"));
//System.out.println(map);
/*
//先获取map集合的所有键的Set集合
Set<String> keySet = map.keySet();
//获取其迭代器
Iterator<String> it = keySet.iterator();
while (it.hasNext()){
String key=it.next();
//
String value = map.get(key);
System.out.println("key:"+key+",value:"+value);
}
*/
}
}
练习:"adfgctjkgfs"获取字符串中的字母出现的次数
打印结果:{a=4, b=2, c=2, d=2, e=1, f=1, g=2, h=2, j=2, s=2, y=1}
想要打印结果:a(4)b(2)c(2)
1、将字符串转换成数组,
2、定义map结合,因为打印结果字母有顺序,使用TreeMap
3、遍历字符数组
4、将map集合中的数据变成指定的字符串形式返回。
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class GetCount {
public static void main(String[] args){
String str=charCount("abcdefgachgsyajabhdjs");
System.out.println(str);
}
public static String charCount(String str){
char[] chs = str.toCharArray();
TreeMap<Character,Integer> tm = new TreeMap<Character, Integer>();
int count=0;
for (int i=0;i<chs.length;i++){
if(!(chs[i]>='a'&&chs[i]<='z'||chs[i]>='A'&&chs[i]<='Z'))
continue;
Integer value=tm.get(chs[i]);
if(value!=null)
count=value;
count++;
tm.put(chs[i],count);
count=0;
/*
if(value==null){
tm.put(chs[i],1);
}else {
value=value+1;
tm.put(chs[i],value);
}
*/
}
//System.out.println(tm);
//遍历完之后存起来
StringBuilder sb = new StringBuilder();
Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator();
while (it.hasNext()){
Map.Entry<Character,Integer> me =it.next();
Character ch=me.getKey();
Integer value=me.getValue();
sb.append(ch+"("+value+")");
}
return sb.toString();
}
}
1)Hashtable: 底层是哈希表数据结构,不可以存入null键和null值,线程同步
2)HashMap:底层是哈希表数据结构,允许null键和null值,非线程同步
3)TreeMap: 底层是二叉树数据结构,线程不同步,可以用于给Map集合中key进行排序。和Set很像,Set底层就是使用了Map集合。
引申:hashmap和hashtable区别
同:都实现map接口,都采用hash法进行索引
异:
1)hashmap是hashtable的轻量级实现(非线程安全实现),前者允许空键值(最多只允许一条记录),而后者不允许
2)hashmap把hashtable的contains方法去掉了,改成containsvalue和containskey
3)前者非线程安全,效率高
4)前者使用Iterator,后者使用Enumeration
5)前者,hash数组默认大小为16,而且一定是2的指数,后者默认大小是11,增加方式2倍+1
map扩展:
大集合嵌套小集合
问题:Collection和Collections区别
Collections 是集合框架的工具类
static void sort(List<T> list):排序