集合
认识集合
1:数组长度固定不变,不能很好地适应数量动态变化地情况。虽然可以通过.length来获取数组地长度,但是不能直接获取数组中实际存储地元素个数。数组采用在内存中分配连续空间地存储方式存储数据,根据元素信息查找时效率比较低,需要进行多次比较。针对数组的缺陷,Java集合提供了一套性能优良,使用方便的接口和类,它们都位于java.util包中。其主要内容和彼此之间的关系如下图所示:
2:从集合关系图中可以看出,java集合类主要由Map接口和Collection接口派生而来,其中Collection接口有两个常用的子接口,即List和Set接口,List接口的实现有ArrayList类和LinkedList实现,Set接口有实现类HashSet。
List接口实践
1 概述:List接口继承自Collection接口,用户可以使用索引访问List接口中的元素,类似于数组,List接口允许存放重复元素,也就是说List可以存储一组不唯一,有序的对象。
2:使用ArrayList类动态存储数据
ArrayList可以存储不同数据类型的数据,并且添加的数据将转换为Object类型,且和数据采用相同的数据存储方式,在内存中分配连续的空间。
package collection;
import java.util.*;
public class m_list
{
public static void main(String[] args)
{
//这里指定了存储的数据类型,也可以不指定
ArrayList<String> string_list = new ArrayList<String>();
string_list.add("小三");
string_list.add("小舞");
string_list.add("me");
//判断集合是否存在"唐三"
System.out.println("判断集合是否存在唐三");
System.out.println(string_list.contains("唐三"));
string_list.set(2,"唐三");
//移除索引为2的数据
string_list.remove(2);
for(int i=0;i<string_list.size();i++)
{
String name = (String) string_list.get(i); //根据索引来取得元素
System.out.println(name);
}
//获取指定元素的下标
System.out.println(string_list.indexOf("小三"));
System.out.println("**************************************");
//存储的数据都转换为obj
for(Object obj:string_list)
{
System.out.println("看一看obj是什么");
System.out.println(obj);
String name_1 = (String)obj;
System.out.println(name_1);
}
System.out.println("判断集合是否为空");
System.out.println(string_list.isEmpty());
}
}
set(index,obj):该方法会判断index是否在xxlist.length的范围内,如果在就将原来index位置的元素替换为现在的obj。而add()方法具有插入的作用,他会重新调整原来的位置。在小标为1的位置插入"dd",将会导致原来小标为1的元素的下标变为2.
//这里指定了存储的数据类型,也可以不指定
ArrayList<String> string_list = new ArrayList<String>();
string_list.add("小三");
string_list.add("小舞");
string_list.add("me");
//在指定的位置 插入元素
string_list.add(1,"dd");
System.out.println(string_list.get(2));//输出小舞
3:使用LinkedList来存储数据:
(1)概述:ArrayList和数据采用了相同的数据存储方式,在内存中分配连续的内存空间,因此在添加和删除非尾部元素时会导致后面所有元素的移动,这就造成在插入、删除等操作频繁的应用场景下使用ArrayList会导致性能低下。所以数据操作频繁时,最好使用LinkedList存储数据。
(2)LinkedList特点:LinkedList类是List接口的链接列表实现类。它支持实现所有List接口可选的列表的操作,并且允许元素值是任何数据,包括null。LinkedList类采用链表存储方式存储数据,优点在于插入、删除元素时效率比较高,但是LinkedList类的查找效率很低。
(3):使用LinkedList来存储汽车品牌,
package collection;
import java.util.*;
class m_car{
public int price;
public String name;
m_car()
{
System.out.println("执行m_car.class的无参构造函数");
}
m_car(int price,String name)
{
this.setname(name);
this.setprice(price);
}
void setprice(int price)
{
this.price = price;
}
void setname(String name)
{
this.name = name;
}
int getprive()
{
return this.price;
}
String getname()
{
return this.name;
}
@Override
public String toString()
{
return "["+"{"+this.name+","+this.price+"}"+"]";
}
}
public class m_linklist {
public static void main(String[] args)
{
m_car car1 = new m_car(430000,"大奔");
m_car car2 = new m_car(43000,"三菱");
m_car car3 = new m_car(300000,"林肯大陆");
m_car car4 = new m_car(200000,"红旗");
//使用LinkedList创建list集合
LinkedList car_list = new LinkedList();//在这里可以不指定存储数据的类型
car_list.add(car2);
car_list.add(car3);
}
}
(4)使用addfirst()和addLast()方法插入数据
//使用addfirst()添加数据到头部
car_list.addFirst(car1);
//使用addlast()方法添加数据到尾部
car_list.addLast(car4);
System.out.println("插入头条和末尾数据完成");
(5):使用getLast()和getFirst()方法来获取末尾的数据和第一条数据,这里的输出由继承自object类中的toString()方法来实现,在java中每一个类都继承object类.
m_car car_1 = (m_car) car_list.getFirst();
System.out.println(car_1);
m_car car_4 = (m_car) car_list.getLast();
System.out.println(car_4);
/*
输出
[{大奔,430000}]
[{红旗,200000}]
*/
(6):删除头条和尾部的数据
//删除头条和尾部的数据
car_list.removeFirst();
car_list.removeLast();
(7):使用remove(index)方法来删除指定下标的数据,比如删除下标为1后,其下标为0的对象的一个指针将一样指向下标为1的对象,而此时下标为1的数据为当初下标为2的对象。这里需要理解java链表结构,可以查阅java数据结构来理解他的原理.
car_list.remove(1);
System.out.println(car_list.size());
System.out.println(car_list.get(1));
/*输出
3
[{林肯大陆,300000}]
*/
Set接口简单的使用
1.概述:Set接口描述的是一种比较简单的集合,集合中的对象并不支持不按特定的方式排序,并且并不按特定的方式排序,并且不能保存重复的对象,也就是说Set接口可以存储一组唯一,无序的对象。Set接口常用的实现有HashSet。
2:在不知道数据的下标的情况下如果需要查找一条数据,这时候我们知道LinkedList和数据已经ArrayList就吗,没有必要考虑了,他们的数据结构决定了他们的查找效率低下,所以这时候HashSet就是一个最好的选择。这里需要查阅相关书籍理解Hash这种数据结构(算法)。
3:HashSet的特点:
(1):集合内的元素是无序的;
(2):HashSet类是非线程安全的;
(3):允许集合元素值为null。
4:HashSet案例:
package collection;
import java.util.*;
class m_car{
public int price;
public String name;
m_car()
{
System.out.println("执行m_car.class的无参构造函数");
}
m_car(int price,String name)
{
this.setname(name);
this.setprice(price);
}
void setprice(int price)
{
this.price = price;
}
void setname(String name)
{
this.name = name;
}
int getprive()
{
return this.price;
}
String getname()
{
return this.name;
}
@Override
public String toString()
{
return "["+"{"+this.name+","+this.price+"}"+"]";
}
}
public class m_HashSet {
public static void main(String[] args) {
m_car car1 = new m_car(430000,"大奔");
m_car car2 = new m_car(43000,"三菱");
m_car car3 = new m_car(300000,"林肯大陆");
m_car car4 = new m_car(200000,"红旗");
//实例化HashSet
Set car_hashset = new HashSet();
car_hashset.add(car1);
car_hashset.add(car2);
//输出其大小
System.out.println(car_hashset.size());//输出2
//判断是否存在car1这条数据
System.out.println(car_hashset.contains(car1));//输出true
//遍历,HashSet是无序的存储数据,所以不存在索引,也就不存在get(index)方法
for(Object obj:car_hashset)
{
m_car name = (m_car) obj;
System.out.println(name);
/*
输出
2
true
[{大奔,430000}]
[{三菱,43000}]
*/
}
}
}
Map接口
1概述:Map接口存储一组成对的键(key)值对,提供key到value的映射,通过key来检索。Map接口中的key不要求有序,不允许重复。value同样不要求有序,但允许重复。
2:使用用的HashMap类动态存储数据,其优点是查询指定元素效率高。
package collection;
import java.util.*;
class m_car{
public int price;
public String name;
m_car()
{
System.out.println("执行m_car.class的无参构造函数");
}
m_car(int price,String name)
{
this.setname(name);
this.setprice(price);
}
void setprice(int price)
{
this.price = price;
}
void setname(String name)
{
this.name = name;
}
int getprive()
{
return this.price;
}
String getname()
{
return this.name;
}
@Override
public String toString()
{
return "["+"{"+this.name+","+this.price+"}"+"]";
}
}
public class m_hashmap {
public static void main(String[] args) {
m_car car1 = new m_car(430000,"大奔");
m_car car2 = new m_car(43000,"三菱");
m_car car3 = new m_car(300000,"林肯大陆");
m_car car4 = new m_car(200000,"红旗");
Map car_map = new HashMap();
//使用put(object key,object value)来插入数据
car_map.put("奔驰牌",car1);//注意该方法的参数类型
car_map.put("三零宏观牌",car2);//注意该方法的参数类型
car_map.put("林肯大陆牌",car3);//注意该方法的参数类型
car_map.put("红旗牌",car4);//注意该方法的参数类型
System.out.println("已经添加的车牌数=="+car_map.size());
//输出键集合
System.out.println("键集:"+car_map.keySet());
//根据指定的键值来查询到需要的数据
String name = "红旗牌";
m_car car_information;
if(car_map.containsKey(name))
{
/*
数据添加到HashMap集合后,所有数据的数据类型将转换为Object类型,
所以从其中获取数据时需要进行强制类型转换。
*/
car_information = (m_car)car_map.get(name);
}else{
System.out.println("不存在该车牌名");
}
//遍历key值
for(Object key:car_map.keySet())
{
System.out.println(key.toString());
}
//遍历学生详细信息
for(Object value:car_map.values())
{
m_car car_value = (m_car)value;
System.out.println(car_value);
}
}
}
泛型在集合中的应用
1泛型概述:泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数,使代码可以应用于多种类型。
2定义:将对象的类型作为参数,指定到其他类或者方法上,从而保证类型转换的安全性和稳定性,这就是泛型。其本质是参数化类型。
3:定义格式:
/*
类1或者接口<类型实参>对象 = new 类2<类型实参>();
【注意】:
首先,“类2”可以是“类1”本身,可以是“类1”的子类,还可以是接口的实现类;其次,“类2”的类型实参必须与“类1”中的类型实参相同。
【例如】
ArrayList<String> m_list = new ArrayList<String>();
*/
4:案列
package collection;
import java.util.*;
class m_car{
public int price;
public String name;
m_car()
{
System.out.println("执行m_car.class的无参构造函数");
}
m_car(int price,String name)
{
this.setname(name);
this.setprice(price);
}
void setprice(int price)
{
this.price = price;
}
void setname(String name)
{
this.name = name;
}
int getprive()
{
return this.price;
}
String getname()
{
return this.name;
}
@Override
public String toString()
{
return "["+"{"+this.name+","+this.price+"}"+"]";
}
}
public class fanxing {
public static void main(String[] args) {
m_car car1 = new m_car(430000,"大奔");
m_car car2 = new m_car(43000,"三菱");
m_car car3 = new m_car(300000,"林肯大陆");
m_car car4 = new m_car(200000,"红旗");
List<m_car> car_list = new ArrayList<m_car>();
car_list.add(car1);
car_list.add(car2);
car_list.add(car3);
car_list.add(car4);
for(m_car car:car_list)
{
System.out.println(car);
}
}
}
/*
输出
[{大奔,430000}]
[{三菱,43000}]
[{林肯大陆,300000}]
[{红旗,200000}]
*/