集合

集合

由来:对象用于封装特有数据,对象多了需要存储,如果对象的个数不确定,就是用集合容器进行存储

集合特点:
1 用于存储对象的容器。
2 集合的长度是可变的。
3 集合中不可以存储基本数据类型值。


集合容器因为内部的数据结构不同,有多种具体容器。
不断的向上抽取,就形成了集合框架。

框架的顶层Collection接口:

Collection的常见方法:
 booleanadd(E e)
          确保此 collection 包含指定的元素(可选操作)。
 booleanaddAll(Collection<? extendsE> c)
          将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
 voidclear()
          移除此 collection 中的所有元素(可选操作)。
 booleancontains(Object o)
          如果此 collection 包含指定的元素,则返回 true
 booleancontainsAll(Collection<?> c)
          如果此 collection 包含指定 collection 中的所有元素,则返回 true
 booleanequals(Object o)
          比较此 collection 与指定对象是否相等。
 inthashCode()
          返回此 collection 的哈希码值。
 booleanisEmpty()
          如果此 collection 不包含元素,则返回 true
 Iterator<E>iterator()
          返回在此 collection 的元素上进行迭代的迭代器。
 booleanremove(Object o)
          从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
 booleanremoveAll(Collection<?> c)
          移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
 booleanretainAll(Collection<?> c)
          仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
 intsize()
          返回此 collection 中的元素数。
 Object[]toArray()
          返回包含此 collection 中所有元素的数组。
<T> T[]
toArray(T[] a)
          返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。


迭代器Iterator 
boolean hasNext()
          如果仍有元素可以迭代,则返回 true
 Enext()
          返回迭代的下一个元素。
 voidremove()
          从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
  
Iterator  对象必须依赖于具体容器,因为每一个容器的数据结构都不同。所以该迭代器对象是在
容器中进行内部实现的。对于使用容器者而言,具体地实现不重要,只要通过容器获取到该实现
的迭代器的对象即可,也就是iterator方法。
Interator 接口就是对所有的Collection容器进行元素取出的公共接口。
例:
public static void show1(Collection c1){
c1.add("abc1");
c1.add("abc2");
c1.add("abc5");
//使用Object 中的iterator方法获取Iterator 的一个对象
Iterator it = c1.iterator();

遍历全部元素一:
while(it.hasNext()){
System.out.println(it.next());
}

遍历全部元素二:
for(Iterator it = c1.iterator();it.hasNext();){
System.out.println(it.next());
}


List : 有序(存入和取出的顺序一致),元素 都有索引(角标),元素可以重复。

Set:元素不能重复。无序 ,方法与Collection一致

List:特有的常见方法: 有一个共性特点就是可以操作角标。
1 添加
void add(index,element)
void add(index,collection)
2 删除
Object remove(index)//返回被删掉的元素
3 修改
Object set(index,element)
4 获取
Object get(index)
int indexOf(object)
int lastIndexOf(object)
List subList(from,to) //包含头不包含尾
List  可以完成对元素的增删改查

例:
public class ListDemo {
public static void main(String[] args) {
  List list = new ArrayList();
  list.add("abc1");
  list.add("abc2");
  list.add("abc3");
  ListIterator it = list.listIterator();//获取列表迭代器对象 ListIterator为 Iterator的子接口
  while(it.hasNext()){ //它可以实现在迭代过程中完成对元素的增删改查
  //注意只有List集合具备该迭代功能
 Object obj = it.next();
 if(obj.equals("abc2")){//在
 }迭代器过程中,不要使用集合操作元素,容易出现异常
 it.add("abc9");// ListIterator 迭代器有add方法
 }
  System.out.println(list);

注意:
  /*
  Iterator it = list.iterator();
  while(it.hasNext()){
 Object obj = it.next();
 if(obj.equals("abc2")){//在迭代器过程中,不要使用集合操作元素,容易出现异常
 list.add("abc9");//java.util.ConcurrentModificationException
 }
 else
 System.out.println("next:"+obj);
 }
  System.out.println(list);
  */

  }
}

List:常用子类
1 Vector:内部是数组数据结构,是同步的。
2 ArrayList:内部是数组数据结构,是不同步的。替代了Vector 查询速度快
3 LinkedList:内部是链表数据结构,是不同步的。 增删元素快
以上长度都是可变的。

LinkedList 练习:
 请用LinkedList来模拟一个堆栈或者队列数据结构。
  堆栈:先进后出结构
  队列:先进先出结构
  应该描述这样一个容器,提供一个对象完成这两种数据结构
 
class DuiLie{

private LinkedList list;
DuiLie(){
list = new LinkedList();
}
public void myadd(Object obj){
list.addLast(obj);
}
public Object myGet(){
return list.removeFirst();
}
public boolean isNull(){
return list.isEmpty();
}
}

public class LinkedTest {

public static void main(String[] args) {

DuiLie d = new DuiLie();
d.myadd("abc1");
d.myadd("abc2");
d.myadd("abc3");
while(!d.isNull()){
System.out.println(d.myGet());
}
}
}

ArrayList练习:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
}



public class ArrayTest {
public static void main(String[] args) {

ArrayList arr = new ArrayList();
arr.add(new Person("lisi1",21));
arr.add(new Person("lisi2",22));
arr.add(new Person("lisi3",23));
arr.add(new Person("lisi4",24));
Iterator it = arr.iterator();
while(it.hasNext()){

//System.out.println(( (Person) it.next()).getName()+"::"+((Person) it.next()).getAge());
//这里如果直接加getName() 会报错,因为it.next() 返回的是
//Object对象,而Object没有getName方法 所以得强制转换
//如果这里为两个next()就会输出lisi1::22
 //lisi3::24 因为next()是一次一次执行的 不会一次执行两个next()

Person p = (Person) it.next();
System.out.println(p.getName()+"--"+p.getAge());
}
}
}

ArrayList练习:
 去除ArrayList 中的相同元素
思路:
  1 用另一个ArrayList 存储其中的元素
  2 判断已存入元素是否含有将要存入的元素,如果没有,则存入
 
 


public class ArrayListDemo {
public static void main(String[] args) {

ArrayList a = new ArrayList();

a.add(new Person("lisi1",22));
a.add(new Person("lisi1",22));
a.add(new Person("lisi1",23));
a.add(new Person("lisi1",23));
System.out.println(a);

a =  getSingleElement(a);
System.out.println(a);

}
public static ArrayList getSingleElement(ArrayList a){
ArrayList tmp = new ArrayList();
Iterator it = a.iterator();
while(it.hasNext()){
Object obj = it.next();
if(!tmp.contains(obj))//如果判断的为自定义的对象,其实 contains方法调用的是equals 方法。
tmp.add(obj);
}
return tmp;
}
}

set的常用子类:
1 HashSet: 内部数据结构是哈希表,是不同步的。
HashSet的子类LinkedHashSet可以使元素变得有序。 
哈希值:根据对象本身利用算法得出一个值,从而确定它的位置。

哈希表确定元素是否相同:
1 判断的是两个元素的哈希值是否相同。
如果相同,在判断两个对象的内容是否相同
2 判断哈希值相同,其实判断的是对象的hashCode的方法。判断内容相同,用的是equals方法。
注意:如果哈希值不同,是不需要判断equals。



练习:
  往HashSet 存储Person对象,如果姓名年龄相同,则视为同一个元素。
 

public class HashTest {

public static void main(String[] args) {

HashSet hs = new HashSet();

/* 每个对象的地址不同,equals比较就是不同的,所以HashSett会认为有五个对象。
* 所以需要 在Person 中重写HashCode 方法和equals

Person 重写equals方法
/*
 public boolean equals(Object obj) {
if(this==obj)
return true;
if(!(obj instanceof Person))
return false;
Person p = (Person)obj;
return this.name.equals(p.name)&&this.age==p.age;
}
public int hashCode() {
return name.hashCode()+age;
}
*/


hs.add(new Person("lisi4",24));
hs.add(new Person("lisi7",27));
hs.add(new Person("lisi7",27));
hs.add(new Person("lisi1",21));
hs.add(new Person("lisi9",29));
Iterator it = hs.iterator();
while(it.hasNext()){
Person p = (Person) it.next();
System.out.println(p.getName()+"...."+p.getAge());
}
}
}

2 TreeSet::可以对set集合中的元素进行排序,是不同步的。
判断元素唯一性的方式:根据比较方法的返回结果是否为0,为0就是相同元素
Tree对元素进行排序的方式之一:
让元素自身具备比较功能, 元素就需要实现Comparable接口。覆盖compareTo方法。(大于返回一个正整数,小于返回负整数,小于返回0)
如果不按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序中,怎么办?
可以使用TreeSet集合第二种排序方式二:
让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。
将该类对象作为参数传递给TreeSet集合的构造函数。

方式一:

public class TreeSetDemo {
public static void main(String[] args) {

/*TreeSet会进行排序,而此时Person类没有继承Comparable,所以无法比较。
在Person类实现Comparator接口实现方法:
public int compareTo(Object obj) {

第二种方式(简写):Person p = (Person)obj;
int tmp = this.age-p.age;
return tmp==0?this.name.compareTo(p.name):tmp;//String类已经实现了Comparable

第一种方式:Person p = (Person)obj;
if(this.age>p.age)
return 1;
if(this.age<p.age)
return -1;
else{
return this.name.compareTo(p.name);   // 年龄相等的情况下,比较姓名。
}
*/


TreeSet set = new TreeSet();
set.add(new Person("wangwu",29));
set.add(new Person("lisi",22));
set.add(new Person("sayu",21));
set.add(new Person("lisi",23));
Iterator it = set.iterator();
while(it.hasNext()){
Person p = (Person)it.next();
System.out.println(p.getName()+":"+p.getAge());

}

}
}


方式二:

public class TreeSetDemo {
public static void main(String[] args) {


/*
public class CompareByName implements Comparator {
public int compare(Object a, Object b) {
Person p1 = (Person)a;
Person p2 = (Person)b;
int tmp = p1.getName().compareTo(p2.getName());
return tmp==0?p1.getAge()-p2.getAge():tmp;  //如果想要按照输入顺序进行排序,直接返回1
}
}*/



TreeSet set = new TreeSet (new CompareByName());
set.add(new Person("wangwu",29));
set.add(new Person("lisi",22));
set.add(new Person("sayu",21));
set.add(new Person("lisi",23));
Iterator it = set.iterator();
while(it.hasNext()){
Person p = (Person)it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}
}



小Tips:
需要唯一吗?
需要:Set:
需要制定顺序吗?
需要:TreeSet
不需要:HashSet(需要一个和存储一致的顺序时:LinkedHashSet)
不需要:List

需要频繁增删吗?
需要:LinkedList
不需要:ArrayList

List
1 ArrayList
2 LinkedList
Set
1 HashSet
2 TreeSet
后缀名就是该集合所属的体系。
前缀名就是该集合的数据结构。
看到array:就要想到数组,就要想到查询快,有角标
看到Link:就要想到链表,就要想到增删快,就要想到add,get,remove+first,last的方法
看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashCode方法和equals方法
看到tree:就要想到二叉树,想到排序,想到两个接口Comparable,Comparator

通常这些容器是不同步的。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Map:一次添加一对元素。Collection 一次添加一个元素。
Map也称为双列集合,Collection集合称为单列集合。
其实Map集合中存储的就是键值对。
map集合中必须保证键的唯一性。

常用方法:
1 添加:
value put(key,value):返回前一个和key关联的值,如果没有返回null  (键值相同,值会覆盖)
2 删除
void clear();清空map集合
value remove(key):根据指定的key得出这个值。
3 判断
boolean containKey(key):
boolean conyainValue(value):
boolean isEmpty();
4 获取
value get(key):通过键获取值,如果没有该键返回null
当然可以通过返回null,来判断是否包含指定键。
int size();获取键值对的个数。

其他方法:
Set<Map.Entry<K,V>>entrySet()
          返回此映射中包含的映射关系的 Set 视图。


 Collection<V>values()
          返回此映射中包含的值的 Collection 视图。

 Set<K>keySet()
          返回此映射中包含的键的 Set 视图。

取出元素:
public class MapDemo {
public static void main(String[] args) {

Map<Integer,String> map = new HashMap<Integer,String>();
method(map);
}

public static void method(Map<Integer,String> map){

/*取出map的所有元素:
原理:通过keySet()方法获取键的Set集合,再通过Set的迭代器获取每一个键
最后通过map的get()方法获取每一个键对应的值
*/

map.put(1, "a");
map.put(2, "b");
map.put(3, "c");
Set<Integer> keySet = map.keySet();
Iterator<Integer> it = keySet.iterator();
while(it.hasNext()){
Integer key = it.next();
String value = map.get(key);
System.out.println(key+":"+value);
}
}
}

第二种方法 entrySet
*/
/*通过Map转成Set就可以迭代
* 第二种方法 entrySet
* 该方法将键和值得映射关系作为对象存储到了Set集合中,而这个映射关系类型就是Map.Entry类型
* */
(接上面)例:
Set<Map.Entry<Integer,String>> entrySet = map.entrySet();//Entry为Map的静态内部接口
Iterator<Map.Entry<Integer,String>> it = entrySet.iterator();
while(it.hasNext()){
Map.Entry<Integer,String> me = it.next();
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key+"::"+value);

}

Map常用的子类:

1 Hashtable:内部结构是哈希表,是同步的。不允许null作为键,null作为值

2 HashMap: 内部结构是哈希表,不是同步的。允许null作为键,null作为值

子类:LingkedHashMap:取出的顺序和存储一的顺序一致。

3 TreeMap;每部结构是二叉树,不是同步的。可以对Map集合中的键进行排序

4 Properties:用来存储键值对型的配置文件的信息,可以和io技术相结合。


练习:
"vavavbafafs" 记录字符串中字符出现的次数
 * 按格式输出:例:a(1) b(2) c(2)

/*"vavavbafafs" 记录字符串中字符出现的次数
 * 按格式输出:例:a(1) b(2) c(2)
 * 思路:因为字符与次数存在映射关系,所以可以用Map集合存储这些映射关系。
 * 因为字符输出格式是有序的,所以可以用TreeMap存储。
 * 1 将字符串转换为字符数组。
 * 2 遍历字符数组,判断Map集合中是否含有该字符,有的话,取出对应的字符(键)的值
 * 使值加1;再把字符作为键存入Map集合(键相同,值会覆盖),没有的话字符作为键,1作为值进行存储。
 * 3 遍历结束
 * */


public class MapTest {

public static void main(String[] args) {

String str = "vav   a ++   vba  A fa DDfs";
String s = getCharCount(str);
System.out.println(s);
}


public static String getCharCount(String str) {

// 将字符串变为字符数组 toCharArray()
char[] chs = str.toCharArray();

// 建立一个Map集合
Map<Character, Integer> map = new TreeMap<Character, Integer>();// TreeMap对键进行排序
// 进行判断
for (int i = 0; i < chs.length; i++) {
if (!((chs[i] >= 'a' && chs[i] <= 'z') || (chs[i] >= 'A' && chs[i] <= 'Z')))
continue;
Integer s = map.get(chs[i]);
if (s == null) {
map.put(chs[i], 1);
} else {
s++;
map.put(chs[i], s);
}
}
return maptoString(map);
}


private static String maptoString(Map<Character, Integer> map) {

StringBuilder sb = new StringBuilder();
Iterator<Character> it = map.keySet().iterator();
while (it.hasNext()) {
Character key = it.next();
Integer value = map.get(key);
sb.append(key + "(" + value + ")");
}
return sb.toString();
}
}

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

集合框架工具类
Collections
static
<T> int
binarySearch(List<? extendsComparable<? super T>> list, T key)
          使用二分搜索法搜索指定列表,以获得指定对象。
static
<T> int
binarySearch(List<? extends T> list, T key,Comparator<? super T> c)
          使用二分搜索法搜索指定列表,以获得指定对象。
static
<T extends Object & Comparable<? super T>>
T
max(Collection<? extends T> coll)
          根据元素的自然顺序,返回给定 collection 的最大元素。
static
<T> T
max(Collection<? extends T> coll,Comparator<? super T> comp)
          根据指定比较器产生的顺序,返回给定 collection 的最大元素。
static
<T extends Object & Comparable<? super T>>
T
min(Collection<? extends T> coll)
          根据元素的自然顺序 返回给定 collection 的最小元素。
static
<T> T
min(Collection<? extends T> coll,Comparator<? super T> comp)
          根据指定比较器产生的顺序,返回给定 collection 的最小元素。
static voidreverse(List<?> list)
          反转指定列表中元素的顺序。
static
<T> Comparator<T>
reverseOrder()
          返回一个比较器,它强行逆转实现了 Comparable 接口的对象 collection 的自然顺序
static
<T extends Comparable<? super T>>
void
sort(List<T> list)
          根据元素的自然顺序 对指定列表按升序进行排序。
static
<T> void
sort(List<T> list,Comparator<? super T> c)
          根据指定比较器产生的顺序对指定列表进行排序。
static voidswap(List<?> list, int i, int j)
          在指定列表的指定位置处交换元素。
static
<T> Collection<T>
synchronizedCollection(Collection<T> c)
          返回指定 collection 支持的同步(线程安全的)collection。
static
<T> List<T>
synchronizedList(List<T> list)
          返回指定列表支持的同步(线程安全的)列表。
static
<K,V> Map<K,V>
synchronizedMap(Map<K,V> m)
          返回由指定映射支持的同步(线程安全的)映射。
static
<T> Set<T>
synchronizedSet(Set<T> s)
          返回指定 set 支持的同步(线程安全的)set。
static
<K,V> SortedMap<K,V>
synchronizedSortedMap(SortedMap<K,V> m)
          返回指定有序映射支持的同步(线程安全的)有序映射。
static
<T> SortedSet<T>
synchronizedSortedSet(SortedSet<T> s)
          返回指定有序 set 支持的同步(线程安全的)有序 set。


Arrays的方法都是静态的
重点:Arrays工具的List   asList(数组)将数组转成集合。
好处:其实可以使用集合的方法操作数组中的元素。
注意:数组的长度是固定的,所以对集合的增删方法是不可以使用的
否则会发生UnsupportedOperationException
如果数组中的元素是对象,那么转成集合时,直接将数组中的元素作为集合中的元素进行集合存储。
如果数组中的元素是基本数据类型数值,那么会将该 数组作为集合中的元素进行存储。

jdk1.5新特性
Collection 继承了Iterable ,它只有一个iterator方法
foreach语句
 格式for(类型 变量:集合|数组){} 简化迭代的书写

函数可变参数   int... (注意:可变参数需要写在方法的列表里,变长的参数必须放在形参的最后,一个方法不能接受两组变长参数)
可变长参数可以理解为用数组存储数据
例:实现多个数的相加
public void add(int...nums){
int sum = 0;
for(int i =0;i<nums.length;i++){ sum+=nums[i] ; }
}

静态导入
import static java.util.Collection.*;    其实导入的是类中的静态成员
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值