`

Java学习系列(七)Java面向对象之集合框架详解(上)

 
阅读更多

Java集合

有时也将集合称为容器类,它的作用就是用来“装对象”的。这里要注意的是集合也可以是对象。下面先看一张图:

HashSet:底层用一个数组存元素 --而且这个数组的长度永远是2的N次方。

HashSet底层就是HashMap实现的。
HashSet的构造器:HashSet(int initialCapacity, float loadFactor)
--initialCapacity:控制底层数组的长度。
如果传入数组长度不是2的N次方,HashSet会自动扩展到2的N次方。
--loadFactory:当HashSet感觉到底层数组快满时,它会再次创建一个长度是原来数组长度2倍的数组。原有的数组就变成垃圾,并且要把原有数组中的元素复制到新数组中,这个过程也叫“重hash”。loadFactory越小,越耗内存;loadFactory越大,性能越低。

举例说明1:

 

public class Test {
	public static void main(String[] args) {
		//没有泛型限制的集合
		Collection c1 = new HashSet();	
		c1.add(1);//本来1不是对象,无法装入集合,但由于jdk提供的自动装箱功能,它会将1包装成对象
		c1.add(new Date());
		//加入泛型限制的集合,意味着该集合只能装“指定类型”的对象。
		//jdk1.7可使用"菱形语法"将new HashSet<String>换成new HashSet<>
		Collection<String> c2 = new HashSet<String>();
		//c2.add(1);错误:只能装String类型的对象
		c2.add("张三");
		c2.add("李四");
		c2.add("王五");
		//判断集合是否包含指定元素
		System.out.println(c2.contains("张三"));
		System.out.println(c2.contains("赵六"));
		//遍历Set集合,有两种方式:1)foreach循环,2)迭代器
		System.out.print("使用foreach循环遍历:");
		for(String e : c2){
			System.out.print(e+" ");
		}
		Iterator<String> it = c2.iterator();
		System.out.print("\n使用迭代器遍历:");
		while(it.hasNext()){
			System.out.print(it.next()+"  ");
		}
		System.out.println();
		Collection<String> c3 = new HashSet<String>();
		c3.add("张三");
		c3.add("王五");
		c3.add("赵六");
		//求差集c2-c3
//		c2.removeAll(c3);
//		System.out.println("c2与c3差集:"+c2);
		//求并集
//		c2.addAll(c3);
//		System.out.println("c2与c3并集"+c2);
		//求交集
		c2.retainAll(c3);
		System.out.println("c2与c3交集:"+c2);
	}
}

 

举例说明2:

 

public class TestHashSet {
	public static void main(String[] args) {
		HashSet<String> hs = new HashSet<String>(3);//底层数组容量会自动会展到4(注意:2的N次方)
		hs.add("1");
		hs.add("2");
		hs.add("3");
		hs.add("4");
		hs.add("5");
		//当HashSet感觉到底层数组快满时,它会再次创建一个长度是原来数组长度2倍的数组,此时新的数组长度为8
		System.out.println(hs);
	}
}

 

HashSet存入机制:

1)当有元素加进来时,HashSet会调用该对象的hashCode()方法,得到一个int值;

2)根据hashCode()返回的int值,计算出它在HashSet的存储位置(数组中的索引);

3)如果要加入的位置是空的,直接方法即可。如果要加入的位置已经有元素,此处就会形成“链表”,数组越满,就越有可能出现链表。

HashSet取元素机制:

1)当有元素加进来时,HashSet会调用该对象的hashCode()方法,得到一个int值;

2)根据hashCode()返回的int值,计算出它在HashSet的存储位置(数组中的索引);

3)如果该位置恰好是要找的元素,直接取出即可。如果该位置有“链表”,HashSet要“挨个”地搜索链表里的元素。

HashSet怎么才会认为两个对象是相等的?(要求自定义类的hashCode()和equals()方法是一致的,即方法中所用到的关键属性要一致)

1、两个对象的hashCode()返回值相等;

2、两个对象通过equals比较返回true。

LinkedHashSet(HashSet的一个子类):它与HashSet的存储机制相似,但LinkedHashSet额外地有一个链表,这个链表可以保证LinkedHashSet能记住元素的添加顺序。

TreeSet(sortedset接口的实现类):它保证Set里添加的元素后是“大小排序”的。底层用一个“红黑树”存放元素。

举例说明(使用TreeSet要求集合元素必须是可以比较大小的):

 

public class TestTreeSet1 {
public static void main(String[] args) {
TreeSet<Integer> ts = new TreeSet<Integer>();
ts.add(3);
ts.add(1);
ts.add(2);
ts.add(5);
ts.add(4);
System.out.println(ts);
}
}
public class TestTreeSet2 {
	public static void main(String[] args) {
		TreeSet<String> ts = new TreeSet<String>();
		ts.add("t");
		ts.add("r");
		ts.add("e");
		ts.add("e");
		System.out.println(ts);//字符串的大小
	}
}

TreeSet元素存入、检索的性能也比较好。
Java的比较大小有两种方式:
A. --自然排序。所有集合元素要实现Comparable接口。
B. --定制排序。要求创建TreeSet时,提供一个Comparator对象(负责比较元素大小)。
举例说明:

 

 

class Apple implements Comparable<Apple> {
	private double weight;// 规定:苹果重量大的苹果越大

	public Apple(double weight) {
		this.weight = weight;
	}

	@Override   //自然排序
	public int compareTo(Apple obj) {
		return this.weight > obj.weight ? 1 : this.weight < obj.weight ? -1 : 0;
	}
     
	@Override
	public String toString() {
		return "Apple[weight=" + this.weight + "]";
	}
}

public class TreeSetTest {

	public static void main(String[] args) {
		TreeSet<Apple> set = new TreeSet<Apple>();
		set.add(new Apple(2.3));
		set.add(new Apple(1.2));
		set.add(new Apple(3.5));
		for (Apple ele : set) {
			System.out.println(ele);
		}
	}
}
class Bird {
	private String name;

	public String getName() {
		return name;
	}

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

	@Override
	public String toString() {
		return "Bird[name=" + name + "]";
	}
}

public class TreeSetTest2 {

	public static void main(String[] args) {
		// 如果集合元素本身没有实现Comparable接口
		// 那就要求创建TreeSet时传入一个Comparator对象
		TreeSet<Bird> set = new TreeSet<Bird>(new Comparator<Bird>() {
			@Override
			public int compare(Bird o1, Bird o2) {
				if (o1.getName().compareTo(o2.getName()) > 0) {
					return -1;
				} else if (o1.getName().compareTo(o2.getName()) < 0) {
					return 1;
				} else {
					return 0;
				}
			}
		});
		set.add(new Bird("aabc"));
		set.add(new Bird("abc"));
		set.add(new Bird("Z"));
		set.add(new Bird("dx"));
		System.out.println(set); 
	}
}

ArrayList(JDK1.2)与Vector(JDK1.0,已经过时)都是基于数组实现的,它们的区别如下:
ArrayList(可根据索引来存取元素)是线程不安全的,Vector是线程安全的。
--ArrayList的性能比Vector要好,即使在多线程环境下,可以使用Collections集合工具类的synchronizedXxx方法把ArrayList包装成线程安全的。

 

而LinkedList底层是基于链表实现的,通常认为它的性能比不上ArrayList,它们的区别如下:

ArrayList:由于可以根据底层数组的索引存取元素,所以性能非常快,但当插入元素、删除元素时性能低。

LinkedList:由于底层采用了链表来存储元素,因此根据索引存取元素性能较慢,但当插入、删除元素时性能非常快。
举例说明:

 

public class Test {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("2");
		list.add("1");
		list.add("5");
		list.add("3");
		System.out.println(list);
		list.add(2,"在索引2处插入元素");
		System.out.println(list);
		list.set(2,"在索引2处替换的元素");
		System.out.println(list);
		list.remove(2);
		System.out.println(list);
		//遍历list(类似数组)
		for(int i =0;i<list.size();i++){
			System.out.print(list.get(i)+"   ");
		}
	}
}

Deque集合:功能被限制的线性表。

 

 

//把Deque当成栈用
public class Test {
	public static void main(String[] args) {
		//把Deque当成栈用
		Deque<String> dq = new ArrayDeque<String>();
		//进栈(压栈):后进先出
		dq.push("a");
		dq.push("b");
		dq.push("c");
		dq.push("d");
		//打印首先出栈的元素
		System.out.println(dq.pop());
		//打印访问栈顶的元素
		System.out.println(dq.peek());
	}
}
//把Deque当成队列用:先进先出
public class Test2 {
	public static void main(String[] args) {
		//把Deque当成队列用:先进先出
		Deque<String> dq = new ArrayDeque<String>();
		//从队列尾部入队
		dq.offer("a");
		dq.offer("b");
		dq.offer("c");
		dq.offer("d");
		//从队列头部出队
		System.out.println(dq.poll());
		//打印访问队头元素
		System.out.println(dq.peek());
	}
}

Collections集合工具类:

public class TestCollections {
	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		list.add("a");
		list.add("b");
		list.add("c");
		list.add("d");
		System.out.println(list);
		//对集合进行反转
		Collections.reverse(list);
		System.out.println(list);
		//把b, c位置进行交换
		Collections.swap(list, 1, 2);
		System.out.println(list);
		//将list集合元素进行随机排列
		Collections.shuffle(list);
		System.out.println(list);
		
	}
}

 

 

结束语

今天内容比较多,而且有些和数据结构相关,所以理解起来可能会有些困难。编程我觉得还是要多练,只要你肯多练,就不会那么难了。今天就讲到这,明天开始讲Map。

分享到:
评论

相关推荐

    Java面向对象编程实例详解

    "Java面向对象编程实例详解2.txt"和"Java面向对象编程实例详解.txt"可能包含了详细的讲解和示例代码,涵盖了类的创建、对象的实例化、访问控制、构造函数、抽象类和接口、异常处理、集合框架等方面的知识。...

    Java面向对象程序设计耿祥义版课件

    二、Java面向对象特性详解 1. 抽象:抽象是将共同特征抽取出来形成类的过程,Java通过抽象类和接口实现抽象。 2. 构造器:构造器用于初始化新创建的对象,Java中的构造器与类同名且无返回值。 3. 访问控制修饰符:...

    Java基础教程完整版

    Java学习系列(七):Java面向对象之集合框架详解(上) 本章节主要讲解Java集合框架的上半部分,包括集合框架的概述、Collection接口、List接口、Set接口、Map接口等。 Java学习系列(八):Java面向对象之集合...

    java面向对象基础、高级pdf讲义

    Java面向对象基础与高级知识点详解 Java是一种广泛使用的面向对象编程语言,它的设计哲学是“一切皆对象”。本讲义将全面深入地介绍Java面向对象的基础概念和高级特性,帮助开发者从初学者到精通者逐步提升技能。 ...

    Java集合类详解总结

    ### Java集合类详解总结 在Java编程中,集合框架...Java集合框架的设计充分体现了面向对象编程的原则,提供了灵活且强大的数据结构支持,使得开发者能够更加专注于业务逻辑的实现,而无需过多关注底层数据结构的细节。

    java(面向对象编程)课件

    【Java面向对象编程课件详解】 Java是一种广泛使用的高级编程语言,以其面向对象特性而闻名。面向对象编程(Object-Oriented Programming,OOP)是Java的核心,它将现实世界中的概念映射到代码中,使得程序设计更加...

    朱福喜面向对象与Java程序设计课后答案详解

    面向对象与Java程序设计是软件开发领域中的核心概念,朱福喜的著作深入浅出地讲解了这些主题,为开发者提供了宝贵的资源。本教程重点围绕Java语言和面向对象编程的基本概念,结合课后习题答案,帮助读者巩固理解并...

    完整版 Java初级教程 Java语言程序设计 第8章 集合框架(共19页).ppt

    【Java初级教程】Java语言程序设计的第8章聚焦于集合框架,这是一个核心概念,用于组织和管理数据。集合框架是一套接口和类的体系,提供了处理数据集合的方法。本章的目标是掌握ArrayList、HashSet和HashMap的使用,...

    Java集合框架实现及应用实例-核心数据结构详解与案例演示

    适合人群:对于具有一定编程知识特别是面向对象概念认知的基础程序员或者正在学习/研究Java这门语言的人。 使用场景及目标:为用户提供了一个清晰的学习路径,以便能够快速入门理解并且有效应用集合框架于实际开发...

    Java2编程详解(Special_Edition_Using_Java)

    《Java2编程详解》这本书是Java编程领域的一部经典之作,特别版的使用指南深入剖析了Java 2平台的核心技术和编程方法。这本书旨在帮助开发者掌握Java语言的基础以及高级特性,从而能够有效地进行软件开发。 首先,...

    Java2编程详解

    2. **面向对象编程**:Java是完全面向对象的语言,它支持类、对象、封装、继承、多态等面向对象特性。理解类和对象的概念,学会如何设计和实现类,以及掌握继承和多态的应用,对于编写可维护、可扩展的代码至关重要...

    java编程思想详解

    此外,Java的集合框架,如ArrayList、HashMap等,为数据存储和操作提供了便利。 Java从C/C++发展而来,但它在内存管理和安全性上有显著改进。Java的垃圾回收机制自动管理内存,避免了内存泄漏,而它的类型检查和...

    Java面向对象程序设计模拟试题

    根据给定的文件信息,我们可以总结出以下关于Java面向对象程序设计的重要知识点: ### Java面向对象基础 #### 1. 对象的创建与释放 - **创建对象**: 在Java中,使用`new`关键字来创建一个新的对象实例。例如,创建...

    Java集合排序及java集合类详解(Collection、List、Map、Set).pdf

    Java集合框架的设计理念是基于面向对象的设计模式,它遵循了开闭原则、单一职责原则、依赖倒置原则等设计原则。 本文详细解释了Java集合框架的实现原理、Collection、List、Set、Map四个接口的定义和实现原理,...

    java2编程详解 java学习

    Java2编程详解主要涵盖Java语言的核心概念和技术,包括但不限于语法基础、面向对象编程、类与对象、接口与抽象类、异常处理、输入/输出(I/O)系统、集合框架、多线程、网络编程以及Java的高级特性。以下是对这些主题...

    Java2编程详解.rar

    1. **面向对象编程**:Java是一种完全面向对象的编程语言,支持类、接口、继承、封装和多态等概念。理解这些基础是学习Java的起点。 2. **类和对象**:Java中的所有代码都基于类,类是创建对象的蓝图。了解如何定义...

    java2编程详解(special_edition_using_java)

    3. **数组与集合框架**:介绍如何使用数组存储和操作数据,并深入探讨Java的集合框架,如ArrayList、LinkedList、HashSet、HashMap等容器类的使用。 4. **异常处理**:讲解Java中的异常处理机制,如何捕获和处理...

    最新Java 编程详解

    2. **集合框架**:Java集合框架是处理对象数组的重要工具,包括List(如ArrayList和LinkedList)、Set(如HashSet和TreeSet)、Map(如HashMap和TreeMap)以及接口如Iterable和Iterator。 3. **异常处理**:Java中...

    Java案例详解1精通Java项目开发

    1. **Java编程基础**:学习Java语言的基本语法,包括变量、数据类型、控制结构(如if-else,switch,循环)、类与对象、封装、继承和多态等面向对象特性。这些都是Java项目开发的基础。 2. **Java集合框架**:Java...

Global site tag (gtag.js) - Google Analytics