At the moment, I'm solving the following problem: I need to implement a public static buildDefinitionList() method that generates an HTML list of definitions (tags <dl>, <dt> and <dd>) and returns the resulting string. If there are no elements in the array, the method returns an empty string.
The method takes as input a list of definitions in the form of a two-dimensional array:
String[][] definitions = {
{"definition1", "description1"},
{"definition2", "description2"},
};
That is, each element of the input array is itself an array containing two elements: a term and its definition.
String[][] definitions = {
{"Bulb", "Bulge, thickening on the surface of something"},
{"Beaver", "An animal from the order of rodents"},
};
HtmlBuilder.buildDefinitionList(definitions);
// "<dl><dt>Bulb</dt><dd>Bulge, thickening on the surface of something</dd><dt>Beaver</dt><dd>An animal from the order of rodents</dd></dl>";
Here is my code:
package com.arrays.problem6;
public class HtmlBuilder {
public static void main(String[] args) {
}
public static String buildDefinitionList(String[][] definitions){
var result = new StringBuilder();
result.append("<dl><dt>");
for (var item : definitions) {
result.append("<dd>");
result.append(item);
result.append("</dl></dd>");
}
result.append("</dl></dd>");
return result.toString();
}
}
The program is working in the right direction, but so far I can not find the error. Please help me find it.
Still, I had to figure it out on my own. I didn’t need nested loops. It’s all about creating two additional string variables that are written to a two-dimensional array. Well, I also needed the same check for the absence of elements in the array.
public class HtmlBuilder {
public static void main(String[] args){
}
public static String buildDefinitionList(String[][] definitions){
if(definitions.length==0){
return "";
}
StringBuilder result = new StringBuilder();
result.append("<dl>");
for(String[] definition : definitions){
String name=definition[0];
String description=definition[1];
result.append("<dt>");
result.append(name);
result.append("</dt>");
result.append("<dd>");
result.append(description);
result.append("</dd>");
}
result.append("</dl>");
return result.toString();
}
}
I used TreeSet for this and it works in a per snapshot style. In other words, sort once displays once.
Now, I want to implement a realtime sorted table.
Whenever there is a value change in any elements, the sorted table will be updated accordingly.
To make the sorting work on a per update style, I tried to remove the element and add it to the TreeSet again.
quotes.remove(quote);
quotes.add(quote);
It doesn't work because I have to implement the sorting logic in compareTo() but it breaks the contract for identifying the object which makes the remove() work. TreeSet never call equals() and hashcode() as described in the Java Doc.
Any idea? Please advise.
code:
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String args[]) {
TreeSetTest test = new TreeSetTest();
test.onQuoteUpdate("appl", 1000d);
test.onQuoteUpdate("msft", 2000d);
test.onQuoteUpdate("face", 3000d);
test.printTopStocks();
test.onQuoteUpdate("msft", 5000d);
test.printTopStocks();
}
private Set<Quote> quotes = new TreeSet<Quote>();
public void onQuoteUpdate(String symbol, double turnover) {
final Quote quote = new Quote(symbol, turnover);
quotes.remove(quote);
quotes.add(quote);
}
public void printTopStocks() {
System.out.println("--Top Stocks By Turnover--");
for (final Quote quote : quotes) {
System.out.println(quote);
}
}
public static class Quote implements Comparable<Quote> {
private String symbol;
private double turnover;
public Quote(String symbol, double turnover) {
this.symbol = symbol;
this.turnover = turnover;
}
#Override
public int compareTo(Quote o) {
return Double.compare(o.turnover, turnover);
// return symbol.compareTo(o.symbol);
}
}
}
Update 1:
As proposed I tried this:
public static void main(String args[]) {
TreeMapTest test = new TreeMapTest();
test.onQuoteUpdate("appl", 1000d);
test.onQuoteUpdate("msft", 2000d);
test.onQuoteUpdate("face", 3000d);
test.printTopStocks();
test.onQuoteUpdate("face", 50d);
test.printTopStocks();
}
public int compareTo(Quote o) {
if(o.symbol.equals(symbol)) return 0;
return Double.compare(o.turnover, turnover);
}
The remove() return false which eventually there are four elements (expected 3) in the Set.
--Top Stocks By Turnover--
Quote [symbol=face, turnover=3000.0]
Quote [symbol=msft, turnover=2000.0]
Quote [symbol=appl, turnover=1000.0]
remove symbol face : false
add symbol face : true
--Top Stocks By Turnover--
Quote [symbol=face, turnover=3000.0]
Quote [symbol=msft, turnover=2000.0]
Quote [symbol=appl, turnover=1000.0]
Quote [symbol=face, turnover=50.0]
Update 2:
I tried PriorityQueue and here is the code:
https://code.sololearn.com/cb38Eo036c8y/#java
It doesn't work because PriorityQueue doesn't store elements in order. The ordering only works when you poll element from the Queue.
Update 3:
Tried user54321's suggestion that by using a custom collection(see below answer). However, it doesn't look good if there are two more elements having the same value of 'turnover'.
My requirement is a very ordinary one. It seems that none of a collection from JDK fits my case.
Update 4:
The solution from user54321 fits for my interim need.
https://code.sololearn.com/c14Ybab7AOFm/#java
Deleted my previously added answer. Looks like a wrong data structure is being used for the scenario.
Here is why.
When an item is being added or removed, TreeSet does a binary search through the available elements using compareTo().
In your case,
After adding first 3 elements, set looks like this.
[{appl, 1000d}, {msft, 2000d}, {face, 3000d}]
Now when you try to remove the element {face, 50d},
It starts searching at {msft, 2000d},
From compareTo() result it determines {face, 50d} should come before {msft, 2000d}.
And continues to search towards start of the elements ( checking with {appl, 1000d} next).
Since the search doesn't find {face, 3000d}, that element remains without being removed.
Next when you add the element {face,50}, similar search happens and since the search does not find {face, 3000},
It adds {face, 50} to the beginning.
Now the set looks like this.
[{face, 50}, {appl, 1000d}, {msft, 2000d}, {face, 3000d}]
Now the problem here is that compareTo() isn't capable of considering both symbol and turnover for a sensible sorting.
TreeSet can be used for getting a sorted collection of unique elements.
If you need to get a sorted collection of different objects with a particular sorting criteria, in this case turnover value, you can use a PriorityQueue
Update: Using a List and a Set in custom data structure
The problem here is that we have to maintain two conditions.
1. Symbol has to be unique
2. Collection should be sorted by turnover value
compareTo() in Quote can check one at a time and not both.
So in this case we may have to go for a custom data structure.
First use only turnover in compareTo();
#Override
public int compareTo(Quote o) {
return Double.compare(o.turnover, turnover);
}
Then implement the custom data structure.
Note that we are using a HashSet to keep track of the symbol alone.
Using a list so that duplicate turnover values can be kept.
static class QuoteCollection {
Set<String> symbols = new HashSet<>();
List<Quote> quotes = new LinkedList<>();
public void onQuoteUpdate(Quote q) {
if (symbols.contains(q.getSymbol())) {
// this requires quotes.equals() to be implemented
quotes.remove(q);
} else {
symbols.add(q.getSymbol());
}
insertToCollection(q);
}
// inserting at correct position to remain sorted
private void insertToCollection(Quote q) {
int index = Collections.binarySearch(quotes, q);
if (index < 0)
index = ~index; // bitwise compliment to find insert position if it is not available in the list
quotes.add(index, q);
}
public List<Quote> getQuotes() {
return quotes;
}
}
Then use it in the main(). Note that printTopStocks() has been changed a little.
public static void main(String args[]) {
Main test = new Main();
QuoteCollection quoteCollection = new QuoteCollection();
quoteCollection.onQuoteUpdate(new Quote("appl", 1000d));
quoteCollection.onQuoteUpdate(new Quote("msft", 2000d));
quoteCollection.onQuoteUpdate(new Quote("face", 3000d));
test.printTopStocks(quoteCollection.getQuotes());
quoteCollection.onQuoteUpdate(new Quote("face", 50d));
test.printTopStocks(quoteCollection.getQuotes());
}
public void printTopStocks(List<Quote> quotes) {
System.out.println("--Top Stocks By Turnover--");
for (final Quote quote : quotes) {
System.out.println(quote);
}
}
This approach does involve data duplication. However a sorted collection can be maintained at linear time complexity(since it uses 'List.remove()')
Couple of points :
Trying to remove elements even when you are adding it first time.
While updating you are trying to remove new element which does not exist in TreeSet. final Quote quote = new Quote(symbol, turnover); here you are building new element which is Quote("face","50d") which does not exist when you are calling quotes.remove(quote);
Below is the one of the way to solve it, I am hard coding oldQuote to keep it short but you can update it:
public void onAdd(String symbol, double turnover) {
final Quote quote = new Quote(symbol, turnover);
quotes.remove(quote);
quotes.add(quote);
}
public void onQuoteUpdate(String symbol, double turnover) {
final Quote newQuote = new Quote(symbol, turnover);
final Quote oldQuote = new Quote("face", 3000d);
quotes.remove(oldQuote);
quotes.add(quote);
}
public static void main(String args[]) {
TreeSetTest test = new TreeSetTest();
test.onAdd("appl", 1000d);
test.onAdd("msft", 2000d);
test.onAdd("face", 3000d);
test.printTopStocks();
test.onQuoteUpdate("face", 50d);
test.printTopStocks();
}
I'm having trouble understanding what exactly I would put in one of my classes to create the add method for 3 Arrays of the same Type. Here are the generic arrays in the main class
ArrayContainer<Integer> numberContainer = new ArrayContainer<>();
ArrayContainer<String> wordContainer = new ArrayContainer<>();
ArrayContainer<Pokemon> pokedex = new ArrayContainer<>();
My constructor for ArrayContainer is
public ArrayContainer(){
container = (T[]) new Object[defaultSize];
numItems = 0;
}
In my separate class, I'm confused what to put for my
public void add (T item){}
and I'm confused as what to return within my toString. I know you add to an array by putting
arrayName[index] = whatever;
But what would I put in that add method that would add to whatever array I call the method on? Would it be container[index] = item;?
What should I return that would return the element in the array?
Since the number of items in your ArrayContainer is not known beforehand, you should use a dynamic array, also known as List.
The numItems then becomes redundant since you can get it by calling list.size()
Your add function will only need to call list.add. As noted in the comments, it seems you're re-writing/wrapping List
In your toString method, you can return a string that concatenates all results of toString of the items included. StringBuilder can help you create a "format" that suits you. Of course this means that the objects you're putting in the container need to implement toString
Combining all the things will give you something like this:
ArrayContainer
public class ArrayContainer<T> {
private List<T> items;
public ArrayContainer() {
items = new ArrayList<>();
}
public void add(T item) {
items.add(item);
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[ ");
for (T it: items)
sb.append(it.toString()).append(' ');
sb.append(']');
return sb.toString();
}
}
Main
public class Main {
public static void main(String[] args) {
ArrayContainer<String> stringArrayContainer = new ArrayContainer<>();
stringArrayContainer.add("hello");
stringArrayContainer.add("world");
System.out.println(stringArrayContainer);
// Outputs: [hello world]
}
}
The idea is if i am at a certain stair i can either go one step down or two so if am at stair 3 i can go down 1 1 1 or 2 1 for example. My code should print all the possibilities. The error I get is that I can't convert the add function to an array (since the add method is a boolean). What is wrong with this algorithm?
public class Stairs {
public static void staircase (int height ){
ArrayList<Integer> Array = null;
explore (height,Array);
}
public static void explore(int objheight,ArrayList<Integer>Array){
int intialheight = 0;
if (intialheight == objheight){
Array.toString();
}
else{ if (objheight > intialheight ){
explore(objheight-2,Array.add(2));
explore(objheight-1,Array.add(1));
}
}
after your feedback I am getting an empty output
import java.lang.reflect.Array;
import java.util.ArrayList;
public class Stairs {
public static void staircase (int height ){
ArrayList<Integer> Array = new ArrayList<Integer>();
explore (height,Array);
}
public static void explore(int objheight,ArrayList<Integer>Array){
int intialheight = 0;
if (intialheight == objheight){
Array.toString();
}
else{ if (objheight > intialheight ){
Array.add(2);
explore(objheight-2,Array);
Array.add(1);
explore(objheight-1,Array);
}
}}
public static void main (String args[]){
staircase(3);
}
}
The method add(E e) in ArrayList returns true upon appending the element e passed as a parameter to the end of the ArrayList.
Your method, explore(int objHeight, ArrayList<Integer> Array) does not accept a boolean for its second parameter. Yet, in that same method, explore, you are recursively calling explore and passing in a boolean to the method.
The following code should be modified to first invoke the add method of Array and then pass Array to the explore method.
Before:
explore(objheight-2,Array.add(2)); This code is passing parameters int and boolean to the explore method, which is not the parameters it accepts. You should instead attempt the following.
After:
Array.add(2);
explore(objheight-2,Array); This code first adds 2 to the Array and then passes the Array to the explore method without invoking any further methods on the Array object.
You will also need to do this for the next line of code, where you have explore(objheight-1,Array.add(1));.
Edit: Upon further examination of the code, I discovered another (sooner) error that occurs. A NullPointerException will occur each time the program runs:
ArrayList<Integer> Array = null;
explore (height,Array);
Then inside the explore method, different methods on Array are invoked, despite Array always being null:
Array.toString();, Array.add(2) and Array.add(1).
The Array object must be initialized inside of either the staircase or explore methods.
ArrayList<Integer> Array = new ArrayList<Integer>(); or ArrayList<Integer> Array = null;
Array = new ArrayList<Integer>();
I've got two classes in my program, in one I create a HashSet called 'words' and I need to be able to call from that HashSet in the other class, or otherwise copy the HashSet across. I'd prefer to do the former, it seems tidier, but either would be fine.
The code I have at the moment where I want/need to call the HashSet is such:
private void execute(String[] commands)
{
String basicCommand = commands[0];
//this is something I have used in a previous project to call from the HashSet
for (String word : words)
{
if(basicCommand.equals("circle")) {
makeACircle(commands);
}
if(basicCommand.equals(word))
{EMPTY FOR NOW}
else if(basicCommand.equals("help")) {
printHelp();
}
else {
System.out.println("Unknown command: " + basicCommand);
}
}
}`
And the code for my HashSet is:
public String[] getInput()
{
System.out.print("> "); // print prompt
String inputLine = reader.nextLine().trim().toLowerCase();
String[] wordArray = inputLine.split(" "); // split at spaces
// add words from array into hashset
for(String word : wordArray) {
words.add(word);
}
return wordArray;
}
(The HashSet 'words' is defined earlier in the class)
If HashSet is non-static
Create getHashSet() method in your class containing the HashSet. It returns a reference to the hashset.
Create a new instance of the class containing HashSet in the class where you wanna access this HashSet. Call instance.getHashSet();
if HashSet is static
(Its better to make it public as well..)
use ClassContainingHashSet.hashSet to get hashset.
EDIT :
public class MyFirstClass{
public static Set<YourType> mySet = new HashSet<yourType>();
}
class MySecondClass{
public void readHashSet()
{
HashSet<YourType> hs = MyFirstClass.mySet;
}
}
Note : This is not the exact code.. This is sample code.