Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Vangelis Al-Sghir
hs21
Commits
366aee44
Commit
366aee44
authored
Sep 21, 2021
by
Dominik Gruntz
Browse files
01_Collections (solution)
parent
dc2901c4
Changes
6
Hide whitespace changes
Inline
Side-by-side
01_Collections/src/main/java/ch/fhnw/depa/collections/AbstractCollection.java
0 → 100644
View file @
366aee44
package
ch.fhnw.depa.collections
;
import
java.lang.reflect.Array
;
import
java.util.Collection
;
import
java.util.Iterator
;
/**
* A convenience implementation of the java.util.Collection interface. It allows
* to store <code>null<code> elements and supports modifiable collections.
*
* A subclass has to implement methods add(Object x) and iterator().
*
* @param <E>
* the element type of this collection.
*/
public
abstract
class
AbstractCollection
<
E
>
implements
Collection
<
E
>
{
@Override
public
boolean
isEmpty
()
{
return
!
iterator
().
hasNext
();
}
@Override
public
int
size
()
{
int
n
=
0
;
for
(
@SuppressWarnings
(
"unused"
)
E
e
:
this
)
{
n
++;
}
return
n
;
}
@Override
public
boolean
contains
(
Object
o
)
{
for
(
E
e
:
this
)
{
if
(
e
==
o
||
(
o
!=
null
&&
o
.
equals
(
e
)))
{
return
true
;
}
}
return
false
;
}
@Override
public
Object
[]
toArray
()
{
Object
[]
result
=
new
Object
[
size
()];
int
i
=
0
;
for
(
E
e
:
this
)
{
result
[
i
++]
=
e
;
}
return
result
;
}
@Override
@SuppressWarnings
(
"unchecked"
)
public
<
T
>
T
[]
toArray
(
T
[]
arg
)
{
if
(
arg
.
length
<
size
())
{
arg
=
(
T
[])
Array
.
newInstance
(
arg
.
getClass
().
getComponentType
(),
size
());
}
int
i
=
0
;
for
(
E
e
:
this
)
{
arg
[
i
++]
=
(
T
)
e
;
}
if
(
arg
.
length
>
size
())
{
arg
[
i
]
=
null
;
}
return
arg
;
}
@Override
public
boolean
remove
(
Object
o
)
{
Iterator
<
E
>
it
=
iterator
();
while
(
it
.
hasNext
())
{
Object
x
=
it
.
next
();
if
(
x
==
o
||
(
o
!=
null
&&
o
.
equals
(
x
)))
{
it
.
remove
();
return
true
;
}
}
return
false
;
}
@Override
public
void
clear
()
{
Iterator
<
E
>
it
=
iterator
();
while
(
it
.
hasNext
())
{
it
.
next
();
it
.
remove
();
}
}
@Override
public
boolean
containsAll
(
Collection
<?>
c
)
{
for
(
Object
x
:
c
)
{
if
(!
contains
(
x
))
{
return
false
;
}
}
return
true
;
}
@Override
public
boolean
addAll
(
Collection
<?
extends
E
>
c
)
{
boolean
modified
=
false
;
for
(
E
e
:
c
)
{
if
(
add
(
e
))
{
modified
=
true
;
}
}
return
modified
;
}
@Override
public
boolean
removeAll
(
Collection
<?>
c
)
{
boolean
modified
=
false
;
Iterator
<?>
it
=
iterator
();
while
(
it
.
hasNext
())
{
if
(
c
.
contains
(
it
.
next
()))
{
it
.
remove
();
modified
=
true
;
}
}
return
modified
;
}
@Override
public
boolean
retainAll
(
Collection
<?>
c
)
{
boolean
modified
=
false
;
Iterator
<?>
it
=
iterator
();
while
(
it
.
hasNext
())
{
if
(!
c
.
contains
(
it
.
next
()))
{
it
.
remove
();
modified
=
true
;
}
}
return
modified
;
}
}
\ No newline at end of file
01_Collections/src/main/java/ch/fhnw/depa/collections/SimpleCollection.java
0 → 100644
View file @
366aee44
package
ch.fhnw.depa.collections
;
import
java.util.ConcurrentModificationException
;
import
java.util.Iterator
;
import
java.util.NoSuchElementException
;
/**
* This is a very simple implementation of the Collection interface. A
* SimpleCollection may contain the same element more than once and it does
* explicitly not guarantee any order of traversal over its elements.
*
* Moreover it does not support removal of elements.
*
* @param <E>
* Element type of this collection
*/
public
class
SimpleCollection
<
E
>
extends
AbstractCollection
<
E
>
{
private
Node
<
E
>
root
=
null
;
private
int
version
=
0
;
@Override
public
boolean
add
(
E
e
)
{
root
=
new
Node
<
E
>(
e
,
root
);
version
++;
return
true
;
}
@Override
public
Iterator
<
E
>
iterator
()
{
return
new
SCIterator
();
}
private
static
class
Node
<
E
>
{
E
val
;
Node
<
E
>
next
;
Node
(
E
val
,
Node
<
E
>
next
)
{
this
.
val
=
val
;
this
.
next
=
next
;
}
}
@Override
public
int
size
()
{
// this optimization is possible as SimpleCollection does not support
// removal of objects and has only an empty constructor.
return
version
;
}
private
class
SCIterator
implements
Iterator
<
E
>
{
private
Node
<
E
>
current
;
// current refers next element to be returned
private
int
version
;
SCIterator
()
{
current
=
root
;
version
=
SimpleCollection
.
this
.
version
;
}
@Override
public
boolean
hasNext
()
{
if
(
version
!=
SimpleCollection
.
this
.
version
)
{
throw
new
ConcurrentModificationException
();
}
return
current
!=
null
;
}
@Override
public
E
next
()
{
if
(
version
!=
SimpleCollection
.
this
.
version
)
{
throw
new
ConcurrentModificationException
();
}
if
(
current
==
null
)
{
// end of collection reached
throw
new
NoSuchElementException
();
}
E
result
=
current
.
val
;
current
=
current
.
next
;
return
result
;
}
@Override
public
void
remove
()
{
throw
new
UnsupportedOperationException
();
}
}
}
01_Collections/src/main/java/ch/fhnw/depa/collections/SimpleCollection2.java
0 → 100644
View file @
366aee44
package
ch.fhnw.depa.collections
;
import
java.util.ConcurrentModificationException
;
import
java.util.Iterator
;
import
java.util.NoSuchElementException
;
/**
* This is a very simple implementation of the Collection interface. A
* SimpleCollection may contain the same element more than once and it does
* explicitly not guarantee any order of traversal over its elements.
*
* In contrast to the class SimpleCollection, this class supports removal of
* elements.
*
* @param <E>
* Element type of this collection
*/
public
class
SimpleCollection2
<
E
>
extends
AbstractCollection
<
E
>
{
private
Node
<
E
>
root
=
null
;
private
int
version
=
0
;
private
int
size
=
0
;
@Override
public
boolean
add
(
E
e
)
{
root
=
new
Node
<
E
>(
e
,
root
);
version
++;
size
++;
return
true
;
}
@Override
public
Iterator
<
E
>
iterator
()
{
return
new
SCIterator
();
}
private
static
class
Node
<
E
>
{
E
val
;
Node
<
E
>
next
;
Node
(
E
val
,
Node
<
E
>
next
)
{
this
.
val
=
val
;
this
.
next
=
next
;
}
}
@Override
public
int
size
()
{
return
size
;
}
private
class
SCIterator
implements
Iterator
<
E
>
{
private
Node
<
E
>
current
;
// current refers next element to be returned
private
int
version
;
private
Node
<
E
>
last
;
SCIterator
()
{
current
=
root
;
version
=
SimpleCollection2
.
this
.
version
;
}
@Override
public
boolean
hasNext
()
{
if
(
version
!=
SimpleCollection2
.
this
.
version
)
{
throw
new
ConcurrentModificationException
();
}
return
current
!=
null
;
}
@Override
public
E
next
()
{
if
(
version
!=
SimpleCollection2
.
this
.
version
)
{
throw
new
ConcurrentModificationException
();
}
if
(
current
==
null
)
{
// end of collection reached
throw
new
NoSuchElementException
();
}
E
result
=
current
.
val
;
last
=
current
;
current
=
current
.
next
;
return
result
;
}
@Override
public
void
remove
()
{
if
(
version
!=
SimpleCollection2
.
this
.
version
)
{
throw
new
ConcurrentModificationException
();
}
if
(
last
==
null
)
{
throw
new
IllegalStateException
();
}
if
(
root
==
last
)
{
root
=
root
.
next
;
}
else
{
Node
<
E
>
p
=
root
;
while
(
p
.
next
!=
last
)
p
=
p
.
next
;
p
.
next
=
p
.
next
.
next
;
}
SimpleCollection2
.
this
.
version
++;
version
++;
SimpleCollection2
.
this
.
size
--;
last
=
null
;
}
}
}
01_Collections/src/main/java/ch/fhnw/depa/collections/package-info.java
0 → 100644
View file @
366aee44
/**
* This package contains collection implementations used in the introduction lesson
* of the module Design Patterns</a> at
* <a href="www.fhnw.ch/technik">FHNW</a>.
* @author Christoph Denzler
* @author Dominik Gruntz
*
*/
package
ch.fhnw.depa.collections
;
\ No newline at end of file
01_Collections/src/test/java/ch/fhnw/depa/collections/TestSimpleCollection.java
0 → 100644
View file @
366aee44
package
ch.fhnw.depa.collections
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertEquals
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertFalse
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertNotNull
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertNull
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertSame
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
assertTrue
;
import
static
org
.
junit
.
jupiter
.
api
.
Assertions
.
fail
;
import
java.util.Arrays
;
import
java.util.ConcurrentModificationException
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.NoSuchElementException
;
import
org.junit.jupiter.api.AfterEach
;
import
org.junit.jupiter.api.Assertions
;
import
org.junit.jupiter.api.BeforeEach
;
import
org.junit.jupiter.api.Test
;
public
class
TestSimpleCollection
{
private
SimpleCollection
<
Integer
>
col
;
@BeforeEach
public
void
setUp
()
throws
Exception
{
col
=
new
SimpleCollection
<>();
}
@AfterEach
public
void
tearDown
()
throws
Exception
{
}
@Test
public
void
testAdd
()
{
assertEquals
(
0
,
col
.
size
());
assertTrue
(
col
.
add
(
1
));
assertEquals
(
1
,
col
.
size
());
assertTrue
(
col
.
add
(
2
));
assertTrue
(
col
.
add
(
4
));
assertEquals
(
3
,
col
.
size
());
assertTrue
(
col
.
add
(
null
));
assertEquals
(
4
,
col
.
size
());
}
@Test
public
void
testIterator
()
{
// test iterator on empty collection
Iterator
<
Integer
>
it
=
col
.
iterator
();
assertNotNull
(
it
);
assertFalse
(
it
.
hasNext
());
// test iterator on one element collection
col
.
add
(
2
);
it
=
col
.
iterator
();
assertNotNull
(
it
);
assertTrue
(
it
.
hasNext
());
Integer
i
=
it
.
next
();
assertNotNull
(
i
);
assertEquals
(
2
,
i
.
intValue
());
assertFalse
(
it
.
hasNext
());
// test iterator on three element collection
col
.
add
(
11
);
col
.
add
(
11
);
List
<
Integer
>
resultList
=
new
LinkedList
<>(
Arrays
.
asList
(
11
,
11
,
2
));
it
=
col
.
iterator
();
assertNotNull
(
it
);
assertTrue
(
it
.
hasNext
());
i
=
it
.
next
();
assertNotNull
(
i
);
assertTrue
(
resultList
.
remove
(
i
));
assertTrue
(
i
.
intValue
()
==
11
||
i
.
intValue
()
==
2
);
assertTrue
(
it
.
hasNext
());
i
=
it
.
next
();
assertNotNull
(
i
);
assertTrue
(
resultList
.
remove
(
i
));
assertTrue
(
i
.
intValue
()
==
11
||
i
.
intValue
()
==
2
);
assertTrue
(
it
.
hasNext
());
i
=
it
.
next
();
assertNotNull
(
i
);
assertTrue
(
resultList
.
remove
(
i
));
assertTrue
(
i
.
intValue
()
==
11
||
i
.
intValue
()
==
2
);
assertFalse
(
it
.
hasNext
());
assertTrue
(
resultList
.
isEmpty
());
// provoke a no such element exception
final
Iterator
<
Integer
>
fit
=
it
;
Assertions
.
assertThrows
(
NoSuchElementException
.
class
,
()
->
fit
.
next
());
}
@Test
public
void
testIteratorRemove
()
{
col
.
add
(
3
);
col
.
add
(
5
);
Iterator
<
Integer
>
it
=
col
.
iterator
();
try
{
it
.
remove
();
fail
();
}
catch
(
UnsupportedOperationException
e
)
{
}
it
.
next
();
Assertions
.
assertThrows
(
UnsupportedOperationException
.
class
,
()
->
it
.
remove
());
}
@Test
public
void
testIteratorConcurrency
()
{
col
.
add
(
3
);
col
.
add
(
5
);
Iterator
<
Integer
>
it1
=
col
.
iterator
();
Integer
i1
=
it1
.
next
();
assertTrue
(
i1
.
intValue
()
==
3
||
i1
.
intValue
()
==
5
);
col
.
add
(
7
);
// invalidate it1
try
{
it1
.
hasNext
();
fail
();
}
catch
(
ConcurrentModificationException
e
)
{
}
try
{
it1
.
next
();
fail
();
}
catch
(
ConcurrentModificationException
e
)
{
}
try
{
it1
.
remove
();
fail
();
}
catch
(
UnsupportedOperationException
e
)
{
}
Iterator
<
Integer
>
it2
=
col
.
iterator
();
it2
.
next
();
it2
.
next
();
it2
.
next
();
// it2 has reached end of collection
col
.
add
(
11
);
// invalidate it2 anyways
try
{
it2
.
hasNext
();
fail
();
}
catch
(
ConcurrentModificationException
e
)
{
}
try
{
it2
.
next
();
fail
();
}
catch
(
ConcurrentModificationException
e
)
{
}
try
{
it2
.
remove
();
fail
();
}
catch
(
UnsupportedOperationException
e
)
{
}
}
@Test
public
void
testIsEmpty
()
{
assertEquals
(
0
,
col
.
size
());
assertTrue
(
col
.
isEmpty
());
col
.
add
(
1
);
assertFalse
(
col
.
isEmpty
());
}
@Test
public
void
testSize
()
{
assertEquals
(
0
,
col
.
size
());
col
.
add
(
1
);
assertEquals
(
1
,
col
.
size
());
col
.
add
(
1
);
assertEquals
(
2
,
col
.
size
());
col
.
add
(
3
);
assertEquals
(
3
,
col
.
size
());
}
@Test
public
void
testContains
()
{
assertFalse
(
col
.
contains
(
5
));
col
.
add
(
1
);
col
.
add
(
2
);
assertFalse
(
col
.
contains
(
5
));
assertTrue
(
col
.
contains
(
2
));
assertTrue
(
col
.
contains
(
1
));
}
@Test
public
void
testToArray
()
{
Object
[]
arr
=
col
.
toArray
();
assertNotNull
(
arr
);
assertEquals
(
0
,
arr
.
length
);
col
.
add
(
815
);
arr
=
col
.
toArray
();
assertNotNull
(
arr
);
assertEquals
(
1
,
arr
.
length
);
assertEquals
(
815
,
arr
[
0
]);
col
.
add
(
4711
);
arr
=
col
.
toArray
();
assertNotNull
(
arr
);
assertEquals
(
2
,
arr
.
length
);
assertFalse
(
arr
[
0
].
equals
(
arr
[
1
]));
assertTrue
(
arr
[
0
].
equals
(
815
)
||
arr
[
1
].
equals
(
815
));
assertTrue
(
arr
[
0
].
equals
(
4711
)
||
arr
[
1
].
equals
(
4711
));
}
@Test
public
void
testToArrayTArray
()
{
// fill some data into collection
col
.
add
(
815
);
col
.
add
(
4711
);
// test with empty array argument
Integer
[]
orig
=
new
Integer
[
0
];
Integer
[]
arr
=
col
.
toArray
(
orig
);
assertNotNull
(
arr
);
assertFalse
(
arr
==
orig
);
assertEquals
(
2
,
arr
.
length
);
assertFalse
(
arr
[
0
].
equals
(
arr
[
1
]));
assertTrue
(
arr
[
0
].
equals
(
815
)
||
arr
[
1
].
equals
(
815
));
assertTrue
(
arr
[
0
].
equals
(
4711
)
||
arr
[
1
].
equals
(
4711
));
// test with correctly sized array argument
orig
=
new
Integer
[
2
];
arr
=
col
.
toArray
(
orig
);
assertNotNull
(
arr
);
assertSame
(
arr
,
orig
);
assertEquals
(
2
,
arr
.
length
);
assertFalse
(
arr
[
0
].
equals
(
arr
[
1
]));