java设置一个容器_Java容器

容器

容器Collection, 底下有两个接口:Set 和 List

Set:无序不可重复

List:有序可重复

容器Map, 键值段, 一个key对应一个value

ArrayList, LinkedList, Vector

ArrayList底层实现是数组,所以查询较快,而插入较慢。(每插入一个值,之后的索引和值全部要依次延后)

LinkedList底层实现是链表,所以查询慢,而修改和删除块。链表结构是一个链着一个,查询的时候是挨个往后找,所以较慢。而插入新元素的时候只需要断开某个链,重连上新元素。所以修改插入快,而查询慢。

Vector,底层实现也是数组。线程安全,但效率低。ArrayList和LinkedList线程都不安全。

ArrayList

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classTestDemo {public static voidmain(String[] args) {//ArrayList容器

Employee e = new Employee(0001, "Jack", 5000, "Associate", "2017-12");

Employee e1= new Employee(0002, "Rose", 2000, "Intern", "2020-12");

Employee e2= new Employee(0003, "Tom", 10000, "Senior", "2012-12");//泛型,这里的list就只能存储employee对象了

List list = new ArrayList();

list.add(e);

list.add(e1);

list.add(e2);

}//这里的Employee类一般被称为Javabean,也称实体类(只有属性,构造器和相关getter, setter方法)

}

View Code

HashMap, HashTable

HashMap线程不安全,效率高

HashTable线程安全,效率低

Map

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classTestDemo {public static voidmain(String[] args) {//一个map对象对应一行记录

Map map = newHashMap();

map.put("id", 0001);

map.put("name", "Jack");

map.put("salary", 5000);

map.put("title","Associate");

map.put("HireDate","2017-12");

Map map2= newHashMap();

map.put("id", 0002);

map.put("name", "Rose");

map.put("salary", 2000);

map.put("title","Intern");

map.put("HireDate","2020-12");

Map map3= newHashMap();

map.put("id", 0003);

map.put("name", "Tom");

map.put("salary", 10000);

map.put("title","Senior");

map.put("HireDate","2012-12");

}//不用专门构建类, 用类的属性做key

View Code

遍历List, 迭代器 Iterator

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/**

*遍历list和set*/

public classTestDemo {public static voidmain(String[] args) {

List list= newArrayList();

list.add("aaaaa");

list.add("bbb");

list.add("ccccc");//遍历一个list, 可以用for循环

for (int i=0; i

System.out.println(list.get(i));

}//如果是要遍历set, 因为set是无序的,所以for循环不好用了,用Iterator, 迭代器

Set set = newHashSet();set.add("adsa");set.add("adsadd");set.add("adsdasdas");

Iterator iter= set.iterator();while(iter.hasNext()){

String result=(String) iter.next();

System.out.println(result);

}

}

}

View Code

遍历Map

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/**

* for each 和Interator遍历map*/

public classTest {//for-each循环中遍历keys或values。//如果只需要map中的键或者值,你可以通过keySet或values来实现遍历,而不是用entrySet。

Map map = new HashMap();//遍历map中的键

for(Integer key : map.keySet()) {

System.out.println("Key =" +key);}//遍历map中的值

for(Integer value : map.values()) {

System.out.println("Value =" +value);

}//使用Iterator遍历//1. 使用泛型:

Map map = new HashMap();

Iterator> entries =map.entrySet().iterator();while(entries.hasNext()) {

Map.Entry entry =entries.next();

System.out.println("Key =" + entry.getKey() + ", Value =" +entry.getValue());

}//2. 不使用泛型:

Map map = newHashMap();

Iterator entries=map.entrySet().iterator();while(entries.hasNext()) {

Map.Entry entry=(Map.Entry) entries.next();

Integer key=(Integer)entry.getKey();

Integer value=(Integer)entry.getValue();

System.out.println("Key =" + key + ", Value =" +value);

}

}

View Code

泛型

泛型的作用:

1、安全:在编译的时候检查类型安全

2、方便:所有的强制类型转换都是自动的和隐式的,提高代码的重用率

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/**

泛型类,在声明类时声明(加一个括号)

T Type

K V表示Key Value

E 表示element

? 表示不确定类型

在使用时确定类型

注意:

1、泛型只能使用引用数据,不能是基本类型(只能是Integer, 不能是int)

2、泛型声明时字母不能使用静态属性,静态方法

**/

public class Student {private T1 numericScore; //数字分数

private T2 AlphabeticScore; //字母分数

publicT1 getNumericScore() {returnnumericScore;

}public voidsetNumericScore(T1 numericScore) {this.numericScore =numericScore;

}publicT2 getAlphabeticScore() {returnAlphabeticScore;

}public voidsetAlphabeticScore(T2 alphabeticScore) {

AlphabeticScore=alphabeticScore;

}public static voidmain(String[] args) {//使用时指定类型

Student stu = new Student();//安全,类型检查

stu.setAlphabeticScore("A-");

stu.setNumericScore(92.33);//方便,自动类型转换

double it =stu.getNumericScore();

}

}/**

泛型接口,字母只能使用在方法中,不能使用在全局变量*/

public interface Comparator{voidcompare(T t);

}

View Code

HashMap经典储存,分拣,面向对象

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/**

*定义一个student类,属性为: name, classNumber, Score

* 然后将若干student对象放入list中

* 统计每个班级的总分和平均分,分别打印出来*/

public classTestDemo {public static voidmain(String[] args) {

List studentList = new ArrayList();

exam(studentList);

Map rooms = new HashMap();

countScore(rooms,studentList);//打印总分,平均分

printScore(rooms);

}/***

* 将student对象放入list*/

public static void exam(ListstudentList){

studentList.add(new Student("a","001",80));

studentList.add(new Student("b","002",90));

studentList.add(new Student("c","002",70));

studentList.add(new Student("d","001",100));

studentList.add(new Student("e","003",78));

studentList.add(new Student("f","003",82));

studentList.add(new Student("g","003",96));

}/**

*统计分数*/

public static void countScore(Map rooms, ListstudentList){for(Student student: studentList){

String classNumber=student.getClassNumber();double score =student.getScore();//根据班级编号查看Map是否存在该班级,分拣思路

ClassRoom room = rooms.get(classNumber);if (null ==room){

room= newClassRoom(classNumber);

rooms.put(classNumber, room);

}//储存总分

room.setTotal(room.getTotal() +score);

room.getStudentList().add(student);//加入学生

}

}//打印总分与平均分

public static void printScore (Maprooms){

Set> entrySet =rooms.entrySet();

Iterator> iter =entrySet.iterator();while(iter.hasNext()){

Map.Entry entry =iter.next();

ClassRoom room=entry.getValue();double avg = room.getTotal() /room.getStudentList().size();

System.out.println("ClassNumber is" + room.getClassNumber() + "Total Score is" +room.getTotal()+ "Average score is" +avg);

}

}

View Code

自定义类型排序

1、实体类: 实体类实现java.lang.Comparable接口 + 重写 compareTo方法

2、业务排序类:java.util.Comparator + compare

Comparable vs Comparator

Comparable是排序接口,若一个类实现了Comparable接口,就意味着“该类支持排序”。而Comparator是比较器,我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。 Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。

两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。

推荐第二种,原因如下:

1、解耦:与实体类分离

2、方便应对多变的排序规则

第一种,Comparable

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public class Person implements Comparable{

String name;intage;public Person(String name, intage)

{

super();this.name =name;this.age =age;

}publicString getName()

{returnname;

}public intgetAge()

{returnage;

}

@Overridepublic intcompareTo(Person p)

{return this.age-p.getAge(); //重写compareTo方法,按年龄比较大小

}public static voidmain(String[] args)

{

Person[] people=new Person[]{new Person("xujian", 20),new Person("xiewei", 10)};

System.out.println("排序前");for(Person person : people)

{

System.out.print(person.getName()+":"+person.getAge());

}

Arrays.sort(people);

System.out.println("\n排序后");for(Person person : people)

{

System.out.print(person.getName()+":"+person.getAge());

}

}

}

View Code

第二种,comparator, 比较规则与实体类分离,解耦

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/**

* 自定义数据排序*/

public classGoodsApp {public static voidmain(String[] args) {

List goods = new ArrayList();

goods.add(new Good("Car", 100000, 500));

goods.add(new Good("Plane", 1000000, 10));

goods.add(new Good("Bike", 100, 3248293));

System.out.println("排序前..." + "\n" +goods);

System.out.println();

Collections.sort(goods,new GoodsPriceSort());//前面是需要排序的内容,后面是排序规则

System.out.println("排序后..." + "\n" +goods);

}

}//运行结果:

排序前...

[GoodName: Car, AddToFavorite:500, price: 100000.0, GoodName: Plane, AddToFavorite:10, price: 1000000.0, GoodName: Bike, AddToFavorite:3248293, price: 100.0]

排序后...

[GoodName: Plane, AddToFavorite:10, price: 1000000.0, GoodName: Car, AddToFavorite:500, price: 100000.0, GoodName: Bike, AddToFavorite:3248293, price: 100.0]/**

* 一个简单的商品实体类*/

public classGood {privateString name;private doubleprice;private intaddFavorite;publicGood() {

}public Good(String name, double price, intaddFavorite) {this.name =name;this.price =price;this.addFavorite =addFavorite;

}publicString getName() {returnname;

}public voidsetName(String name) {this.name =name;

}public doublegetPrice() {returnprice;

}public void setPrice(doubleprice) {this.price =price;

}public intgetAddFavorite() {returnaddFavorite;

}public void setAddFavorite(intaddFavorite) {this.addFavorite =addFavorite;

}

@OverridepublicString toString() {return "GoodName:" + name +", AddToFavorite:" + this.addFavorite + ", price:" + this.price + "\n";

}

}/**

* 一个用来描述排序规则的类(按价格排序)*/

public class GoodsPriceSort implements java.util.Comparator{

@Overridepublic intcompare(Good o1, Good o2) {//表示如果结果〉0,返回1,相等,返回0,否则返回1//默认是升序,想要降序,所以前面加个负号

return -(o1.getPrice() - o2.getPrice()>0?1:o1.getPrice() == o2.getPrice()?0:-1);

}

}

View Code

TreeSet和TreeMap

TreeSet: 是Set接口的一个实现类,数据不可重复,数据元素可以排序。 对比HashSet: 元素必须重写hashcode和equals方法;

去重:元素比较为0则去重

排序的两种思路:

1、元素本身可以排序,使用Java.lang.Comparable + compareTo

2、排序业务类,用一个类定义排序规则,使用Java.util.Comparator + compare

TreeSet实际就是实现了Comparator接口的一个业务类

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/**

* 注意:TreeSet是在添加数据时排序,如果你更改数据,比如这里把路人甲的指数修改为101,并不改变原来的排序顺序

* 所以,在使用TreeSet时,不要修改数据,可以用Final严格修饰*/

public classTreeSetDemo {public static voidmain(String[] args) {

Person p1= new Person("You", 1);

Person p2= new Person("刘德华", 100);

Person p3= new Person("吴彦祖", 99);

Person p4= new Person("路人甲", 50);//依次放入TreeSet容器中,使用排序的业务类(匿名内部类)

TreeSet persons = new TreeSet(new java.util.Comparator(){public intcompare(Person o1, Person o2){return o1.getHandsomeIndex() -o2.getHandsomeIndex();

}

}//匿名内部类

);//TreeSet在添加数据时排序

persons.add(p1);

persons.add(p2);

persons.add(p3);

persons.add(p4);

System.out.println(persons);

}

}/**

* 实体类实现Comparable接口,重写compareTo方法*/

public class Worker implements java.lang.Comparable{privateString position;private doublesalary;public Worker(String position, doublesalary) {this.position =position;this.salary =salary;

}publicWorker() {

}publicString getPosition() {returnposition;

}public voidsetPosition(String position) {this.position =position;

}public doublegetSalary() {returnsalary;

}public void setSalary(doublesalary) {this.salary =salary;

}

@Overridepublic intcompareTo(Worker o) {return this.salary>o.salary?1:(this.salary==o.salary?0:-1);

}

}public classTreeSetDemo2 {public static voidmain(String[] args) {

Worker w1= new Worker("Clerk", 5000);

Worker w2= new Worker("Engineer", 10000);

Worker w3= new Worker("Manager", 30000);

Worker w4= new Worker("Head", 50000);

TreeSet workers = new TreeSet();

workers.add(w1);

workers.add(w2);

workers.add(w3);

workers.add(w4);

System.out.println(workers);

}

}

View Code

相同点:

TreeMap和TreeSet都是有序的集合,也就是说他们存储的值都是排好序的。

TreeMap和TreeSet都是非同步集合,因此他们不能在多线程之间共享,不过可以使用方法Collections.synchroinzedMap()来实现同步

运行速度都要比Hash集合慢,他们内部对元素的操作时间复杂度为O(logN),而HashMap/HashSet则为O(1)。

不同点:

最主要的区别就是TreeSet和TreeMap分别实现Set和Map接口

TreeSet只存储一个对象,而TreeMap存储两个对象Key和Value(仅仅key对象有序)

TreeSet中不能有重复对象,而TreeMap中可以存在

TreeMap的底层采用红黑树的实现,完成数据有序的插入,排序。

Collections

注意:Collection是一个上层接口,继承它的主要有Set和List

而Collections主要是一个工具类,提供了很多常见的,实用的方法:

Collections.reverse();

Collections.shuffle();

其他容器

队列:Queue单向队列,一端操作 / Deque双向队列,两端操作

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/**

* 使用单向队列Queue模拟银行排队存款*/

public classTreeSetDemo {public static voidmain(String[] args) {

Queue que = new ArrayDeque();//模拟排队情况

for(int i = 0; i<10; i++){

finalint num = i; //因为匿名内部类只能访问final修饰的对象,所以这里需要这一步//匿名内部类

que.offer(new Request() { //offer方法给和add方法都是添加一个元素,区别是当队列满了,add抛出异常,offer返回false

@Overridepublic voiddeposit() {

System.out.println("No." + num + "is depositing...");

}

});

}

process(que);

}interfaceRequest{voiddeposit();

}public static void process(Queueque){

Request request= null;while (null!=(request=que.poll())){ //poll方法给和remove方法都是删除第一个元素,区别是当队列为空,remove抛出异常,poll返回Null

request.deposit();

}

}

}//运行结果

No.0 isdepositing...

No.1 isdepositing...

No.2 isdepositing...

No.3 isdepositing...

No.4 isdepositing...

No.5 isdepositing...

No.6 isdepositing...

No.7 isdepositing...

No.8 isdepositing...

No.9 is depositing...

View Code

Hashtable和其子类Properties

HashMap和Hashtable的区别:

1、* Hashtable线程安全,同步,效率低;HashMap线程不安全,非同步,效率高

2、两者父类不同,Hashtable - Dictionary; HashMap - AbstractMap

3、Hashtable键和值不能为null,HashMap键最多一个Null, 值可以多个Null

Properties:

1、经常用于读写配置文件

2、键和值只能为String

常用的方法:

setProperty(String key, String value)

getProperty(String key)

getProperty(String key, String DefaultValue)

存储

后缀:

.properties

store(OutputStream out, String comments)

store(Writer writer, String comments)

.xml

storeToXML(OutputStream os, String comments) //默认使用UTF-8字符集

storeToXMLOutputStream out, String comments, String encoding)

获取

loadFromXML(InputStream in)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classTestDemo {public static voidmain(String[] args) throws FileNotFoundException, IOException {

Properties pro= newProperties();//存储

pro.setProperty("driver","oracle.jdbc.driver.OracleDriver");

pro.setProperty("url","jdbc:oracle:thin:@localhost:1521:orcl");

pro.setProperty("user","testUser");

pro.setProperty("pwd","123");//存储到e:/others 绝对路径和盘符//存储为properties文件,user = testUser, 直接对等

pro.store(new FileOutputStream(new File("e:/others/db.properties")),"db配置");//存储为xml文件,xml格式

pro.storeToXML(new FileOutputStream(new File("e:/others/db.XMLproperties")),"dbXML配置");//存储为相对路径,和项目摆在一起

pro.store(new FileOutputStream(new File("db.properties")),"db配置"); //不带盘符

pro.store(new FileOutputStream(new File("src/db.properties")),"db配置");//存到src folder底下//读取

pro.load(new FileReader("e:/others/db.properties")); //绝对路径

pro.load(new FileReader("e:/src/db.properties")); //相对路径//获取

String url = pro.getProperty("url","defaultUrl");//根据类路径加载资源配置文件,工作中常用

pro.load(TestDemo.class.getResourceAsStream("/com/test/others/pro/db.properties")); //"/"表示bin目录//当前线程的类加载器

pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("com/test/others/pro/db.properties") ); //""表示bin目录

}

}

View Code

容器的同步控制和只读设置

使容器可以线程安全,使用Collections.synchronizedList();

只读设置:

emptyXXX()

singletonXXX()

unmodifiableXXX()

Guava和Apache:对JDK容器的拓展,工作中常用的工具类

Guava

只读设置:ImmutableList.of

MultiSet.count()  //可以计算每个元素出现的次数,非常方便。 //这里和HashSet不同,MultiSet也是无序,但是可重复

MultiMap //同样是键-值。但是键可以重复。//这样就使得我们可以把键和值对调,完成某些数据的统计

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

/**

* Guava, Multimap*/

public classTestDemo {public static voidmain(String[] args) {

Map courses = new HashMap();

courses.put("Chinese", "Mr.Huang");

courses.put("English", "Mr.Huang");

courses.put("Math", "Mr.Wang");

courses.put("Physics","Mr.Wang");

courses.put("Chemistry", "Mr.Wang");

courses.put("Art", "Ms.Li");//MultiMap

Multimap teachers =ArraryListMultimap.create();//迭代器

Iterator> itr =courses.entrySet().iterator();while(itr.hasNext()){

Map.Entry entry =itr.next();

String key=entry.getKey();

String value=entry.getValue();//转换键和值,存入MultiMap,因为MultiMap的键可以重复,所以不会报错

teachers.put(value, key);

}//查看Multimap

Set keyset =teachers.KeySet();for(String key: keyset){

Collection collection = teachers.get(keys);

System.out.println(key + "--->" +collection);

}

}

}//输出结果

Mr.Huang --->{Chinese, English}

Mr.Wang--->{Math, Physics, Chmistry}

Ms.Li---> {Art}

View Code

Bimap: 键和值都不能重复,Bimap.inverse() 非常实用,可以有效的使键值对调,从而简单的用值找键

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值