一、Set接口介绍
Set与离散数学中的一个“集合”概念类似,集合的特点是无序的和不允许有重复的数据,在java编程中的所谓重复数据是指使用Object的equals()方法进行比较返回true时的两个对象,Set中的顺序也是按照java自己的排序方式与用户放置数据的先后顺序无关,所以我们也可以理解为是“无序”的。在Set中可以放入空值,但同理也只能放一个null 元素。
常用的Set实现类有HashSet、HashTable和TreeSet。
二、HashSet介绍
1、HashSet介绍
HashSet实现了Set接口,同时继承于AbstractSet类。HashSet对每个对象采用哈希散列码hashcode进行存储索引,哈希散列码hashcode由程序在添加时才生成,每个对象之间没有关系,这样在HashSet中进行添加、删除对象或者比较对象,以及随机读取一个对象等操作时运行的时间是一致,不会因为对象数据量的多少的变化影响性能,在很多需要性能而无关顺序的环境下HashSet是一个非常好的选择。
构造方法有4个重载:
HashSet( ); //创建一个默认的散列集合。
HashSet(Collection c); //用c中的元素初始化散列集合。
HashSet(int capacity); //创建一个容量为capacity的散列集合。
HashSet(int capacity, float fillRatio);//创建一个容量为capacity的散列集合,并指定容量填充比
填充比是一个范围在0.0与1.0之间浮点数,它决定容器中的元素的个数与容器容量比值大于指定的填充比时,散列集合容量会自动扩容。对于没有获得填充比的构造函数,默认使用0.75。
常用普通方法
add(Object o)
size()
2、HashSet示例
代码:
//set 无序 没有重复值 HashSet set=new HashSet(); set.add("王五"); set.add("刘宝"); set.add("张三"); set.add("李四");//注意放了多个李四的数据 set.add("李四"); set.add("李四"); set.add("李四"); System.out.println("大小:"+set.size()); //打印出所有的数据,发现和添加的顺序不一致。 Iterator iterator2=set.iterator(); while (iterator2.hasNext()) { Object object = (Object) iterator2.next(); System.out.println(object); }
程序输出如下:
大小:4
张三
李四
刘宝
王五
由上面的输出可知,我们虽然添加了很多个“李四”的数据,然而集合里面只有四个数据,所以说Set中的数据是不可以有重复数据的。另外,通过迭代打印HashSet可以发现,对象存储在集合中看上去是“无序”的。当然也可以覆盖父类的hashcode方法,让getHashCode方法返回一个伪hash值,这样就可以控制排序。
★集合的可迭代(iterator)特性★
集合是对象的容器,在编程中使用集合,既要能够把数据放进去,也得有方法把数据取回来。在容器中依次获取全部对象的过程叫作迭代集合,java设计了迭代器Iterator接口定义了调用迭代的方法,其Iterator的实现类需要根据自身集合的特性完成相应的迭代算法,算法提供了一种枚举容器中每个对象(enumerating the contents of a collection)的方法。这里枚举或迭代/遍历都是同样的意思。
一、TreeSet介绍
TreeSet的数据结构可以理解为是二叉树结构,我们可以使用TreeSet实现排序功能,TreeSet通过定义一个比较器Comparator来完成集合中对象的排序。
二、TreeSet代码示例
我们先定义一个Student类。代码如下:
public class Student { //属性 private String name; private int age; //写操作 public void setName(String name){ this.name=name; } //读操作 public String getName(){ return name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
再定义一个类,在这个类中我们定义了一个TreeSet类的对象。尝试往里面添加几个学生对象。
public class TreeStu { public static void main(String[] args) { Student student1=new Student(); student1.setName("张三1"); student1.setAge(12); Student student2=new Student(); student2.setName("张三2"); student2.setAge(13); Student student3=new Student(); student3.setName("张三3"); student3.setAge(10); Student student4=new Student(); student4.setName("张三4"); student4.setAge(80); TreeSet set=new TreeSet(); set.add(student1); set.add(student2); set.add(student3); set.add(student4); } }
运行程序,程序抛出了以下异常:
虽然上面的代码非常简单,没有任何逻辑,仅仅只是添加了几个数据,但是程序还是出错了,这是因为TreeSet在添加数据的时候,就必须要求数据按照一定的顺序进行组织,这也是二叉树的一个特点。所以我们需要给TreeSet设置一个比较器。
先新建一个类MyTreeComparator实现接口Comparator
public class MyTreeComparator implements Comparator{ //比较的方法 @Override public int compare(Object o1, Object o2) { Student student1=(Student)o1; Student student2=(Student)o2; if(student1.getAge()>student2.getAge()){ return -1; }else if(student1.getAge()在java.util .Comparator接口的定义中,最重要的是compare(T o1, T o2)方法,该方法返回值为负数、0 还是正数,一般选用-1、0、1
-1 :表示o1 权重小于 o2
0 : 表示o1 权重等于 o2
-1 :表示o1 权重大于 o2
Comparator的compare()方法交给被传入的TreeSet自行调用,不需要开发时程序员去调用。
修改上面的TreeStu类,在构造TreeSet时设置比较器,然后再添加数据,
public class TreeStu { public static void main(String[] args) { Student student1=new Student(); student1.setName("张三1"); student1.setAge(12); Student student2=new Student(); student2.setName("张三2"); student2.setAge(13); Student student3=new Student(); student3.setName("张三3"); student3.setAge(10); Student student4=new Student(); student4.setName("张三4"); student4.setAge(80); //把比较器传给TreeSet MyTreeComparator comparator=new MyTreeComparator(); TreeSet set=new TreeSet(comparator); set.add(student1); set.add(student2); set.add(student3); set.add(student4); System.out.println(set.size()); Iterator iterator=set.iterator(); while(iterator.hasNext()){ Student stu=(Student)iterator.next(); System.out.println(stu.getName()+":"+stu.getAge()); } } }打印出所有的学生信息,学生将会按照年龄进行排序。
Map接口和HashMap实现
一、Map接口
Map意为映射,java.util.Map接口规定了一组通过键值对(key-value)方式组织的集合,键必须是唯一的,Map的数据也是不能保证顺序的,也就是Map中数据的顺序与放置数据的先后顺序无关。,其基本的操作是get 和 put,即放置数据和取数据,我们一般是通过键key获得其对应的值value。
我们在通过键取值时,不管数据量,一般其随机访问速度都是一致的,但是如果经常需要遍历整个Map的所有数据,那么Map可能就不是最好的选择。
二、HashMap实现
HaspMap实现了Map接口,所以在键值对存储关系中,顺序是无需考虑,对象放到HashMap中,所在的位置时由哈希来分布在集合中所在的位置,取值时一般不理会这个位置,而是通过键Key去索引取得对象。跟hashSet一样,Hash序列为HashMap的基本操作(get 和 put)提供稳定的性能。
常用方法:
void clear() //从此映射中移除所有映射关系。
boolean containsKey(Object key) //如果此映射包含对于指定键的映射关系,则返回 true。
boolean containsValue(Object value) //如果此映射将一个或多个键映射到指定值,则返回 true。
Set
> entrySet返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。 boolean isEmpty() //返回此映射所包含的映射关系的 Set 视图。
V get(Object key) 如果此映射不包含键-值映射关系,则返回 true。
Set
keySet() 返回此映射中所包含的键的 Set 视图。 V put(K key, V value) 在此映射中关联指定值与指定键。
void putAll(Map extends K,? extends V> m) 将指定映射的所有映射关系复制到此映射中,这些映射关系将替换此映射目前针对指定映射中所有键的所有映射关系。
V remove(Object key) 从此映射中移除指定键的映射关系(如果存在)。
int size() 返回此映射中的键-值映射关系数。
三、示例代码
public class Stu3 { public static void main(String[] args) { HashMap map = new HashMap(); Student stu1 = new Student(); stu1.setNum(1); stu1.setName("刘德华"); Student stu2 = new Student(); stu2.setNum(2); stu2.setName("张学友"); Student stu3 = new Student(); stu3.setNum(3); stu3.setName("曾志伟"); Student stu4 = new Student(); stu4.setNum(3); stu4.setName("刘宝"); // 添加 key=键 value=值 key唯一 map.put("440602", stu2); map.put("440601", stu1); map.put("440603", stu3); map.put("440603", stu4); // 删 // map.remove("440602"); System.out.println("大小:" + map.size()); Student stu = (Student) map.get("440601"); System.out.println(stu.getName()); // 遍历 // 1、取得key。 Set keySet = map.keySet(); // 2、循环 迭代 Iterator iterator = keySet.iterator(); while (iterator.hasNext()) { Object object = iterator.next(); Student student = (Student) map.get(object.toString()); System.out.println(student.getNum() + ":" + student.getName()); } }
properties属性文件
一、properties属性文件
属性文件Properties是hashTable的子类,一种特殊的java资源文件,常被用于记录一些程序运行时的配置数据,这种文件可以“享有”和class一样的待遇,在java的classpath中被加载,要获得当前系统环境值时,可以使用System.getProperties()方法取得。属性文件是以一种键值对(key:value)的文本格式存储数据,以“回车”分隔两个键值对。调用Properties的默认参构造器可以生成一个没有初始值的Properties实例,该实例是待加载资源文件的对象,加载资源可以使用默认类的classpath进行加载:
二、代码示例
1、在src建立一个属性文件
代码如下:
#hello liu=789 user=abc admin=6782、读取配置文件
public void input() { // 属性对象 Properties properties = new Properties(); try { // 1、通过输入流加载到内存中 properties.load(StuProperties.class.getClassLoader() .getResourceAsStream("user.properties")); // 2、读取数据,类似Map格式,后面是默认值 System.out.println(properties.getProperty("admin", "bbbb")); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }当然我们也可以往配置文件中写入内容,在E盘中将会生成一个user.properties的配置文件。代码如下:
// 操作类,修改,删除,添加 public static void output() { Properties properties = new Properties(); // 1、加载到内存中。 try { // 获得在src文件下面的路径 ,, properties.load(new FileReader("e://user.properties")); // 在内存中添加了。添加 properties.setProperty("liu", "789"); // 删除 properties.remove("admin"); // 修改其实就是添加的方法 properties.setProperty("user", "abc"); // 保存 输出到硬盘中 properties.store(new FileWriter("e://user.properties"), "hello"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }