Jmockit: impossible to use returns() with collections and multiple calls? - jmockit

The function I want to mock:
class Bar {
public Set<Foo> getFoos();
}
The code under test:
for (int i = 0; i < n; ++i) {
Bar bar = computeBar();
for (Foo f : bar.getFoos()) {
// code
}
}
Expectations block:
new Expectations() {{
bar.getFoos();
returns(/* what should I put here?? */);
}};

Either write
new Expectations() {{ bar.getFoos(); returns(foo1, foo2, foo3); }};
to return a single set, or
final Set<Foo> foos1 = new HashSet<Foo>(asList(foo1, foo2));
final Set<Foo> foos2 = new HashSet<Foo>(asList(foo3, foo4, foo5));
new Expectations() {{ bar.getFoos(); returns(foos1, foos2); }};
to return a sequence of sets.

Related

Flyweight pattern in this simple net core Api uses more memory ram

I'm trying to aplicate Flyweight method pattern in a simple .net core Api to see how much memory is saved compared to not using the pattern.
I have two methods, the first one creates 5000 objects without uses the pattern and the another creates 5000 object using the pattern. After each of them create the objects, then they call a method that returns the current memory used by the App.
public class MemoryService : IMemoryService
{
private readonly TreeFactory _treeFactory;
public MemoryService()
{
_treeFactory = new TreeFactory();
}
//create without pattern
public long SetObjectsMemory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < 5000; i++)
{
var tree = new Tree()
{
Id = new Random().Next(1, 9999999),
Part = new PartTree()
{
Name = "Nameany",
Bark = "Barkany",
Color = "Colorany"
}
};
trees.Add(tree);
};
return Utilities.GetCurrentMemoryUsed();
}
//crete with flyweight pattern
public long SetObjectsMemoryFactory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < 5000; i++)
{
var tree = new Tree()
{
Id = new Random().Next(1, 9999999),
Part = _treeFactory.GetPartTree("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
}
I use the pattern like a class that uses a list of Parts and return a part object if exists.
public class TreeFactory
{
private static List<PartTree> _parts;
public TreeFactory() {
_parts = new List<PartTree>();
}
public PartTree GetPartTree(string name, string bark, string color)
{
if (_parts.Any(x => x.Name == name && x.Bark == bark && x.Color == color))
{
return _parts.Where(x => x.Name == name && x.Bark == bark && x.Color == color).FirstOrDefault();
}
else {
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
}
}
The way to get the current memory used by the App is using Process of this way (in Utilities class):
public static long GetCurrentMemoryUsed() {
Int64 memory;
using (Process proc = Process.GetCurrentProcess())
{
memory = proc.PrivateMemorySize64 / (1024 * 1024);
}
return memory;
}
And in my Startup i inject the MemoryService like a Singleton. In the controller i use 3 methods for call the functions:
[HttpGet, Route(nameof(WeatherForecastController.GenerateMemory))]
public IActionResult GenerateMemory()
{
var total=_memoryService.SetObjectsMemory();
return Ok(total);
}
[HttpGet, Route(nameof(WeatherForecastController.GenerateLiftMemory))]
public IActionResult GenerateLiftMemory()
{
var total = _memoryService.SetObjectsMemoryFactory();
return Ok(total);
}
[HttpGet, Route(nameof(WeatherForecastController.GetMemory))]
public IActionResult GetMemory()
{
var total = Utilities.GetCurrentMemoryUsed();
return Ok(total);
}
The problem is: When i call in the navigator the method in controller without pattern (/weatherforecast/GenerateMemory), then this returns (current)+2mb, but when i call the method
with pattern (/weatherforecast/GenerateLiftMemory) this returns (current)+3mb.
Why the method with pattern flyweight returns more used MB (growing) than the methods without the pattern ??
The repository with the code for test it. Gitlab repository memory api
The code which uses TreeFactory consumes more memory because its GetPartTree method called many times in a loop so as Linq methods Any and Where inside it. Both of these methods create additional Iterator objects under the hood in order to iterate through the collection and it causes additional memory consumption.
I wrote simple benchmark using BenchmarkDotNet with more options to demonstrate the issue
Extended MemoryService
public class MemoryService : IMemoryService
{
private const int TreeCount = 50000;
private readonly TreeFactory _treeFactory;
public MemoryService()
{
_treeFactory = new TreeFactory();
}
//crea objetos en memoria sin patrones
public decimal SetObjectsMemory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = new PartTree()
{
Name = "Nameany",
Bark = "Barkany",
Color = "Colorany"
}
};
trees.Add(tree);
};
return Utilities.GetCurrentMemoryUsed();
}
//crea objetos en memoria usando patron flyweight
public decimal SetObjectsMemoryFactory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = _treeFactory.GetPartTree("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
public decimal SetObjectsMemoryFactoryImproved()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = _treeFactory.GetPartTreeImproved("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
//crea objetos en memoria usando patron flyweight
public decimal SetObjectsMemoryFactoryWithoutLambda()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = _treeFactory.GetPartTreeWithoutLambda("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
}
Extended TreeFactory
public class TreeFactory
{
private static List<PartTree> _parts;
public TreeFactory()
{
_parts = new List<PartTree>();
}
public PartTree GetPartTree(string name, string bark, string color)
{
if (_parts.Any(x => x.Name == name && x.Bark == bark && x.Color == color))
{
return _parts.Where(x => x.Name == name && x.Bark == bark && x.Color == color).FirstOrDefault();
}
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
public PartTree GetPartTreeImproved(string name, string bark, string color)
{
var existingPart = _parts.Where(x => x.Name == name && x.Bark == bark && x.Color == color).FirstOrDefault();
if (existingPart != null)
return existingPart;
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
public PartTree GetPartTreeWithoutLambda(string name, string bark, string color)
{
for (int i = 0; i < _parts.Count; i++)
{
var x = _parts[i];
if (x.Name == name && x.Bark == bark && x.Color == color)
return x;
}
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
}
Benchmark in a separate console project
class Program
{
static void Main(string[] args)
{
var result = BenchmarkRunner.Run<MemoryBenchmark>();
}
}
[MemoryDiagnoser]
public class MemoryBenchmark
{
private IMemoryService memoryService;
[GlobalSetup]
public void Setup()
{
memoryService = new MemoryService();
}
[Benchmark]
public object SimpleTrees()
{
var trees = memoryService.SetObjectsMemory();
return trees;
}
[Benchmark]
public object FlyTrees()
{
var trees = memoryService.SetObjectsMemoryFactory();
return trees;
}
[Benchmark]
public object FlyTreesImproved()
{
var trees = memoryService.SetObjectsMemoryFactoryImproved();
return trees;
}
[Benchmark]
public object FlyTreesWithoutLambda()
{
var trees = memoryService.SetObjectsMemoryFactoryWithoutLambda();
return trees;
}
}
And its results
Method
Mean
Error
StdDev
Gen 0
Gen 1
Gen 2
Allocated
SimpleTrees
9.040 ms
0.1804 ms
0.2346 ms
718.7500
453.1250
265.6250
4.44 MB
FlyTrees
19.701 ms
0.1716 ms
0.1521 ms
2500.0000
906.2500
437.5000
15.88 MB
FlyTreesImproved
18.075 ms
0.2869 ms
0.2684 ms
1781.2500
625.0000
312.5000
10.92 MB
FlyTreesWithoutLambda
4.919 ms
0.0273 ms
0.0242 ms
421.8750
281.2500
281.2500
2.53 MB

Conversion from NonStrictExceptions to Expectations

I have test cases using NonStrictExpectations in jMockit v 1.22 as follows:
#Mocked Scanner mockScanner;
#Test
public void getNumber496() {
new NonStrictExpectations() {{
mockScanner.nextLine(); result = "496";
}};
int val = PrimeOrPerfect.getNumber(); // calls Scanner.nextLine() for a number
assertEquals(496, val);
}
The mocking works fine.
After upgrading to jMockit v. 1.25 I changed to Expectations (since NonStrictExceptions is deprecated) as shown below:
#Mocked Scanner mockScanner;
#Test
public void getNumber496() {
new Expectations() {{
mockScanner.nextLine(); result = "496";
}};
int val = PrimeOrPerfect.getNumber(); // calls Scanner.nextLine() for a number
assertEquals(496, val);
}
The mocked method always returns null. What's wrong with the new code?
Here is the code for getNumber():
protected static int getNumber() {
logger.info(">>getNumber()");
Scanner scanner = new Scanner(System.in);
boolean validInput = false;
int number;
System.out.println("Enter a whole positive number (0 to quit):");
do {
String line = scanner.nextLine();
logger.info("input number: {}", line);
number = 0;
try {
number = Integer.parseInt(line);
} catch (NumberFormatException e) {
logger.debug("input is invalid: {}", e.toString());
System.err.println("Please enter a positive integer less than 1001.");
continue;
}
if (number < 0 || number > 1000 ) {
logger.debug("input is out of range 1..1000.");
System.err.println("Please enter a valid number between 1 and 1,000 inclusive.");
} else {
validInput = true;
}
} while (!validInput);
// Don't close the scanner because doing so also closes System.in. Do NOT uncomment the line below.
//scanner.close();
logger.info("<<getNumber()");
return number;
}

managed c++ classes crash in create_task

Basically, what is happening is when trying to change a variable of a Managed class (UWP), it crashes. Additionally, it seems to only crash if I try modifying a variable which is created with the app namespace. In other words, if I create a new namspace and managed class, I can modify variables just fine.
void ASynTaskCategories(void)
{
concurrency::task_completion_event<Platform::String^> taskDone;
MainPage^ rootPage = this;
UberSnip::HELPER::ASYNC_RESPONSE^ responseItem = ref new UberSnip::HELPER::ASYNC_RESPONSE();
create_task([taskDone, responseItem, rootPage]() -> Platform::String^
{
//UBERSNIP API 0.4
UberSnip::UBERSNIP_CLIENT* UberSnipAPI = new UberSnip::UBERSNIP_CLIENT();
UberSnipAPI->Http->RequestURL = "http://api.ubersnip.com/categories.php";
UberSnipAPI->Http->request();
taskDone.set(UberSnipAPI->Client->BodyResponse);
responseItem->Body = UberSnipAPI->Client->BodyResponse;
return "(done)";
}).then([taskDone, responseItem, rootPage](Platform::String^ BodyResponse) {
Platform::String^ BR = responseItem->Body;
cJSON* cats = cJSON_Parse(_string(BR));
cats = cats->child;
int *cat_count = new int(cJSON_GetArraySize(cats));
rootPage->Categories->Clear();
GENERIC_ITEM^ all_item = ref new GENERIC_ITEM();
all_item->Title = "All";
rootPage->Categories->Append(all_item);
for (int i = 0; i < *cat_count; i++) {
cJSON* cat = new cJSON();
cat = cJSON_GetArrayItem(cats, i);
string *track_title = new string(cJSON_GetObjectItem(cat, "name")->valuestring);
GENERIC_ITEM gitem;
gitem.Title = "Hi";
GENERIC_ITEM^ ubersnipCategory = ref new GENERIC_ITEM();
ubersnipCategory->Title = _String(*track_title);
rootPage->Categories->Append(ubersnipCategory);
}
});
This does not crash
UberSnipAPI->Http->RequestURL = "http://api.ubersnip.com/categories.php";
but this one does
all_item->Title = "All";
I am almost positive it has something to do with it being in the apps default namespace and it being accessed outside of the main thread ... At least that's what it seems like as that's really the only difference besides the actual class.
This is what GENERIC_ITEM looks like.
[Windows::UI::Xaml::Data::Bindable]
public ref class GENERIC_ITEM sealed {
private:
Platform::String^ _title = "";
Platform::String^ _description;
Windows::UI::Xaml::Media::ImageSource^ _Image;
event PropertyChangedEventHandler^ _PropertyChanged;
void OnPropertyChanged(Platform::String^ propertyName)
{
PropertyChangedEventArgs^ pcea = ref new PropertyChangedEventArgs(propertyName);
_PropertyChanged(this, pcea);
}
public:
GENERIC_ITEM() {
};
property Platform::String^ Title {
Platform::String^ get() {
return this->_title;
}
void set(Platform::String^ val) {
this->_title = val;
OnPropertyChanged("Title");
}
}
property Platform::String^ Description {
Platform::String^ get() {
return this->_description;
}
void set(Platform::String^ val) {
this->_description = val;
OnPropertyChanged("Description");
}
}
void SetImage(Platform::String^ path)
{
Windows::Foundation::Uri^ uri = ref new Windows::Foundation::Uri(path);
_Image = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage(uri);
}
};
I know there is no issue with the class because it works perfectly fine if I run this exact same code on the initial thread.
Any suggestions? Thanks! :D
Figured it out after several hours! In case someone else is having this issue, all you must do is use the Dispatcher to run code on the UI that is not available outside of the UI thread.
void loadCats(UberSnip::HELPER::ASYNC_RESPONSE^ responseItem, MainPage^ rootPage) {
Platform::String^ BR = responseItem->Body;
cJSON* cats = cJSON_Parse(_string(BR));
cats = cats->child;
int *cat_count = new int(cJSON_GetArraySize(cats));
rootPage->Categories->Clear();
GENERIC_ITEM^ all_item = ref new GENERIC_ITEM();
all_item->Title = "All";
rootPage->Categories->Append(all_item);
for (int i = 0; i < *cat_count; i++) {
cJSON* cat = new cJSON();
cat = cJSON_GetArrayItem(cats, i);
string *track_title = new string(cJSON_GetObjectItem(cat, "name")->valuestring);
GENERIC_ITEM gitem;
gitem.Title = "Hi";
GENERIC_ITEM^ ubersnipCategory = ref new GENERIC_ITEM();
ubersnipCategory->Title = _String(*track_title);
rootPage->Categories->Append(ubersnipCategory);
}
}
void ASyncTaskCategories(void)
{
concurrency::task_completion_event<Platform::String^> taskDone;
MainPage^ rootPage = this;
UberSnip::HELPER::ASYNC_RESPONSE^ responseItem = ref new UberSnip::HELPER::ASYNC_RESPONSE();
auto dispatch = CoreWindow::GetForCurrentThread()->Dispatcher;
auto op2 = create_async([taskDone, responseItem, rootPage, dispatch] {
return create_task([taskDone, responseItem, rootPage, dispatch]() -> Platform::String^
{
//UBERSNIP API 0.4
UberSnip::UBERSNIP_CLIENT* UberSnipAPI = new UberSnip::UBERSNIP_CLIENT();
UberSnipAPI->Http->RequestURL = "http://api.ubersnip.com/categories.php";
try{
UberSnipAPI->Http->request();
}
catch (...) {
printf("Error");
}
int err = UberSnip::UTILS::STRING::StringToAscIIChars(UberSnipAPI->Client->BodyResponse).find("__api_err");
if (err < 0) {
if (UberSnip::UTILS::STRING::StringToAscIIChars(UberSnipAPI->Client->BodyResponse).length() < 3) {
return;
}
}
taskDone.set(UberSnipAPI->Client->BodyResponse);
responseItem->Body = UberSnipAPI->Client->BodyResponse;
dispatch->RunAsync(Windows::UI::Core::CoreDispatcherPriority::High, ref new Windows::UI::Core::DispatchedHandler([=]()
{
rootPage->loadCats(responseItem, rootPage);
}));
for (int i = 0; i < 100;) {
}
return "(done)";
}).then([taskDone, responseItem, rootPage](Platform::String^ BodyResponse) {
});
});
//rootPage->loadCats(responseItem, rootPage);
}

Extract common objects from an arraylist

I have a list like shown below. Assume it has 16 Container objects in it. Each Container object is a simple bean, with fields like age, weight, height, etc. How can I create a sub-list that contains common 'Container' objects if a 'Container' object is considered equal if the weight and height are equal?
List<Container> containers = new ArrayList<Container>();
If by "common" containers you mean duplicating ones, then this code might help you:
import java.util.ArrayList;
import java.util.List;
public class CommonContainers {
public static void main(String[] args) {
List<Container> containers = new ArrayList<Container>(16);
for(int i=0; i<13; i++) {
containers.add(new Container(i, i));
}
//add a few duplicating ones
containers.add(new Container(1,1));
containers.add(new Container(5,5));
containers.add(new Container(6,6));
List<Container> sublist = new ArrayList<Container>();
for (Container c1 : containers) {
for (Container c2 : containers) {
if(c1 != c2 && c1.equals(c2)) {
sublist.add(c1);
}
}
}
for (Container c : sublist) {
System.out.println(c);
}
}
private static class Container {
private int weight;
private int height;
#Override
public String toString() {
return String.format("Container[w=%d,h=%d]", weight, height);
}
public Container(int weight, int height) {
this.weight = weight;
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + height;
result = prime * result + weight;
return result;
}
#Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Container other = (Container) obj;
if (height != other.height)
return false;
if (weight != other.weight)
return false;
return true;
}
}
}
If you mean something else or need clarification, please let me know.
Thanks John Smith for giving direction on this question. I used the iterator instead and was able to make a nice solution to what I was looking for. below is the solution. Note that .equals is overriden for the Containers comparison. The technique I used will take the master list and create a sub-list while removing elements from the parent list at the same time. The solution can be called recursivly until you convert the master list into a subset of lists.
public List<Container> extractCommonSubList(
List<Container> masterContainerList) {
List<Container> subList = new ArrayList<Container>();
ListIterator<Container> iterator = masterContainerList.listIterator();
// get first item from master list and remove from master list
Container firstContainer = iterator.next();
iterator.remove();
// Add first container to sublist
subList.add(firstContainer);
while (iterator.hasNext()) {
Container container = iterator.next();
// Search for matches
if (firstContainer.equals(container)) {
// containers are a match, continue searching for matches
subList.add(container);
iterator.remove();
continue;
} else {
break;
}
}
// return common list
return subList;
}

addFirst(E e) Doubly Linked List (Null Pointer Exception)

import java.util.*;
public class MyTwoWayLinkedList<E> extends java.util.AbstractSequentialList<E> {
private Node<E> head, tail;
private int size = 0;
private List<E> list;
/** Create a default list */
public MyTwoWayLinkedList() {
list = new LinkedList<E>();
}
public MyTwoWayLinkedList(E[] objects) {
list = new LinkedList<E>();
for (int i = 0; i < objects.length; i++)
add(objects[i]);
}
/** Return the head element in the list */
public E getFirst() {
if (size == 0) {
return null;
}
else {
return head.element;
}
}
/** Return the last element in the list */
public E getLast() {
if (size == 0) {
return null;
}
else {
return tail.element;
}
}
/** Add an element to the beginning of the list */
public void addFirst(E e) {
Node<E> newNode = new Node<E>(e); // Create a new node
newNode.next = head; // link the new node with the head
head.previous = newNode; //link the old node with new head
head = newNode; // head points to the new node
size++; // Increase list size
if (tail == null) // the new node is the only node in list
tail = head;
}
/** Add an element to the end of the list */
public void addLast(E e) {
Node<E> newNode = new Node<E>(e); // Create a new for element e
if (tail == null) {
head = tail = newNode; // The new node is the only node in list
}
else {
tail.next = newNode;// Link the new with the last node
newNode.previous = tail;
tail = tail.next; // tail now points to the last node
}
size++; // Increase size
}
#Override /** Add a new element at the specified index
* in this list. The index of the head element is 0 */
public void add(int index, E e) {
if (index == 0) {
addFirst(e);
}
else if (index >= size) {
addLast(e);
}
else {
Node<E> current = tail;
for (int i = size - 1; i > index; i--) {
current = current.previous;
}
Node<E> temp = current.next;
current.next = new Node<E>(e);
(current.next).previous = current;
(current.next).next = temp;
size++;
}
}
/** Remove the head node and
* return the object that is contained in the removed node. */
public E removeFirst() {
if (size == 0) {
return null;
}
else {
Node<E> temp = head;
head = head.next;
head.previous = null;
size--;
if (head == null) {
tail = null;
}
return temp.element;
}
}
/** Remove the last node and
* return the object that is contained in the removed node. */
public E removeLast() {
if (size == 0) {
return null;
}
else if (size == 1) {
Node<E> temp = head;
head = tail = null;
size = 0;
return temp.element;
}
else {
Node<E> temp = tail;
tail = tail.previous;
tail.next = null;
size--;
return temp.element;
}
}
#Override /** Remove the element at the specified position in this
* list. Return the element that was removed from the list. */
public E remove(int index) {
if (index < 0 || index >= size) {
return null;
}
else if (index == 0) {
return removeFirst();
}
else if (index == size - 1) {
return removeLast();
}
else {
Node<E> previous = tail;
for (int i = size - 1; i > index; i--) {
previous = previous.previous;
}
Node<E> current = previous.next;
(current.next).previous = previous;
previous.next = current.next;
size--;
return current.element;
}
}
#Override /** Override toString() to return elements in the list */
public String toString() {
StringBuilder result = new StringBuilder("[");
Node<E> current = tail;
for (int i = size - 1; i > 0; i--) {
result.append(current.element);
current = current.previous;
if (current != null) {
result.append(" ,"); // Separate two elements with a comma
}
else {
result.append("["); // Insert the closing ] in the string
}
}
return result.toString();
}
#Override /** Clear the list */
public void clear() {
size = 0;
head = tail = null;
}
#Override /** Override iterator() defined in Iterable */
public ListIterator<E> listIterator() {
Node<E> current = head; // Current index
return list.listIterator();
}
#Override /** Override iterator() defined in Iterable */
public ListIterator<E> listIterator(int index) {
Node<E> current = head; // Current index
for (int i = 0; i < index; i++) { // sets current int to the parameter
current = current.next;
}
return list.listIterator();
}
#Override
public int size()
{
return size;
}
public class Node<E> {
E element;
Node<E> next;
Node<E> previous;
public Node(E element) {
this.element = element;
}
}
}
This is my original class, I will include my test case below but first let me explain my problem. I am trying to create a Doubly linked list and iterate backwards through it. However I am getting a Null Pointer Exception by just adding elements to the list. I have looked over the section of code for my addFirst method for about 2 hours now and don't see any logic errors(doesn't mean there arent any), please help!
Here is my test case as promised.
public class TestMyLinkedList {
/** Main method */
public static void main(String[] args) {
// Create a list for strings
MyTwoWayLinkedList<String> list = new MyTwoWayLinkedList<String>();
// Add elements to the list
list.add("America"); // Add it to the list
System.out.println("(1) " + list);
list.add(0, "Canada"); // Add it to the beginning of the list
System.out.println("(2) " + list);
list.add("Russia"); // Add it to the end of the list
System.out.println("(3) " + list);
list.addLast("France"); // Add it to the end of the list
System.out.println("(4) " + list);
list.add(2, "Germany"); // Add it to the list at index 2
System.out.println("(5) " + list);
list.add(5, "Norway"); // Add it to the list at index 5
System.out.println("(6) " + list);
list.add(0, "Poland"); // Same as list.addFirst("Poland")
System.out.println("(7) " + list);
// Remove elements from the list
list.remove(0); // Same as list.remove("Australia") in this case
System.out.println("(8) " + list);
list.remove(2); // Remove the element at index 2
System.out.println("(9) " + list);
list.remove(list.size() - 1); // Remove the last element
System.out.print("(10) " + list + "\n(11) ");
for (String s: list)
System.out.print(s.toUpperCase() + " ");
list.clear();
System.out.println("\nAfter clearing the list, the list size is "
+ list.size());
}
}
I'm not completely sure why you are using a LinkedList within your own implementation of a Double Linked List. In regards to your question about your addFirst method however, I have the following comments and an example of how I would approach this solution.
Head is null when you call the addFirst method.
Head has not been initialized as a new Node.
Therefore newNode.next = head; is actually newNode.next = null; There is your null pointer exception, I would imagine!
public void addFirst (E e)
{
Node<E> newNode = new Node<E>(e); //create new node
if (head != null){ //if head exists
newNode.next = head; //the new node's next link becomes the old head
}
head = newNode; //the new head is the new node
if (tail == null){ //if the tail is non existent ie head the only object in list
tail = head; //the head and the tail are the same
head.next = tail; //the 'next' value of head will be tail
}
head.prev = tail; //the previous node to head will always be tail
size++;
}
}