Create an array with the keys of nodes - java

I currently have a binary tree setup and would like to create an array with the keys so I can do a heap sort operation on them. How would I go about doing that?
Here is what I currently have:
public static void main(String args[]) throws IOException
{
BufferedReader in = new BufferedReader(new FileReader("employee.txt"));
String line;
Heap employee = new Heap();
while((line = in.readLine())!= null)
{
String[]text = line.split(" ");
employee.insert(Double.parseDouble(text[0]), Double.parseDouble(text[1]));
}
in.close();
}
The binary tree that I am using is pretty standard but I can post it if needed. The "text[0]" segment is what the key is for each node.

One possibility is to use the TreeSet class in combination with a Comparator. The TreeSet can behave like a heap. The class is well documented, but if you have more questions, ask.
EDIT
Take a look here. The accepted answer shows you an implementation of a binary tree. What you need now is a sorting function implementation in that class, which may be triggered at element insertion or manually when needed.
I still don't see how you want to switch a tree into a heap as they are different things. I guess you mean the tree should be "read" say from left to right and so rearranged?

Related

Why does creating a copy of an object still alter instance variables of original object?

I have two classes. Class Algorithm implements a method findIntersections() which is a sweep line algorithm to check for intersections in O(nLogN) time.
It also implements a function addSegments which adds objects of type Segment (two points) to a priority Queue based on the x coordinate.
public class Algorithm {
public PriorityQueue pQueue = new PriortiyQueue();
//This function adds objects of type Segments to a priority queue
public void addSegments(List<Segment> segments) {
pQueue.add(segments);
//do something
}
//This function implements a sweep line algorithm to check for Intersections.
public void findIntersection() {
while (!pQueue.isEmpty()) {
p.poll(); //removes element from Queue
// do something
}
}
}
The other class Model loads data from a CSV file into the priority Queue. This is an intensive process which I only want to do once.
On the other hand, checkForCollissions is called millions of times.
I want to check for collisions between the supplied segment and the rest of the segments added in the priority queue from the csv file
I do not want to be adding elements to the priority queue from scratch each time. This would not be feasible.
public class Model {
public Algorithm algoObj = new Algorithm();
public ArrayList<Segment> algoObj = new ArrayList<>();
public ArrayList<Segment> segments = new ArrayList<>();
public ArrayList<Segment> single_segment = new ArrayList<>();
public boolean loadCSV() {
//read csv file
while ((strLine = br.readLine()) != null) {
segments.add(new Segment()); //Add all segments in CSV file to ArrayLisyt
algo.addSegments(segments); //Adds 4000 objects of type segment to priority Queue
}
}
//This function is called millions of times
public boolean checkForCollisions(segment_to_check) {
single_segment.add(segment_to_check); //Add 1 segment.
algoObj.addSegments(single_segment); //Adds 1 object of type segment to priority Queue
algoObj.findIntersection();
single_segment.remove(new Segment()); //Remove above segment to get back to original data
}
}
TL;DR
The problem I am having is that after the first call of checkForCollisions the priority queue has changed since findIntersection() works by polling elements from the queue, thus altering the queue.
How do I keep the priority queue created by algoObj.addSegments() from changing between function calls?
Does this have to do witch shallow and deep copying as explained here?
I tried creating a copy of the queue at the beginning of the function and then altering the copy:
public boolean checkForCollisions(segment_to_check) {
Algorithm copy = algoObj;
single_segment.add(segment_to_check); //Add 1 segment.
copy.addSegments(single_segment); //Adds 1 object of type segment to priority Queue
copy.findIntersection();
single_segment.remove(new Segment()); //Remove above segment to get back to original data
}
}
This however does not work as it still alters the priority queue of the original algoObj.
I believe this is a beginner's question and stems from my lack of proper understanding when working with OO languages. Any help would be appreciated.
First of all, it is crucial to know that assigning an existing object to another variable does not create a copy of the original object:
MyObject a = new MyObject();
MyObject b = a; // does NOT create a copy!
// now a and b "point" to the same single instance of MyObject!
Some thoughts about your actual problem:
Your priority queue is just a working data structure that is used for the intersection algorithm, and just while the algorithm is running. When its done (so the intersection(s) have been found), it is empty or at least altered, as you already wrote. So the priority queue must be recreated for every algorithm run.
So what you should do:
Load the segments from the CSV file into your ArrayList, but don't pass it to the priority queue yet.
Refill (or recreate) the priority queue every time before calling findIntersection(). This is best be done by passing all segments to the method and creating a new prioerity queue from scratch:
public void findIntersection(Collection<Segment> segments) {
PriorityQueue<Segment> pQueue = new PrioerityQueue<Segment>(segments);
while (!pQueue.isEmpty()) {
p.poll(); //removes element from Queue
// do something
}
}
Hint: As I've already wrote at the beginning, this does not copy the individual segments nor the segment collection. It just passes a references. Of course, the priority queue will have to create internal structures at construction time, so if the segments collection is huge, this may take some time.
If this solution is too slow for your needs, you will have to work on your algorithms. Do you really need to check for intersections so often? If you add just one segment to the list, it should be sufficient to check intersections with the other segments, but not if the other segments intersect each other. Probably you could store your segments in a binary search tree similar to the one used by the Bentley–Ottmann algorithm. Whenever a new segment "arrives", it can be checked against the search tree, which should be doable with a time complexity of about O(log n). After that, the segment can be inserted into the tree, if necessary.
Or maybe you can add all segments first and then check for intersections just once.

Java Load all strings from file into a Set data structure with (key=string, value=line number)

I've been trying to implement a Set data structure with key, value.
I have a txt file (EOL) have a String, line number something like this:
Adam,1
Mary,2
Michael,3
My goal is store this key-value inside a Set.
Here is my code:
public class Main {
public static void main(String[] args)throws Exception
{
Scanner scanner = new Scanner(new FileReader("C:\\Users\\musti\\Desktop\\demo.txt"));
HashMap<String,Integer> mapFirstfile = new HashMap<String,Integer>();
while (scanner.hasNextLine()) {
String[] columns = scanner.nextLine().split(",");
mapFirstfile.put(columns[0],Integer.parseInt(columns[1])); }
// HashMap sıralı yazdırmaz, LinkedHashSet sıralı tutar, ama ekstradan linkedlist lazım.
System.out.println(mapFirstfile);
System.out.println(mapFirstfile.keySet());
System.out.println(mapFirstfile.values());
Set<HashMap> setFirstfile = new HashSet<HashMap>();
}
This is not an answer actually, but too long for comment...
First of all, Set is a structure of unique (in regards to equals()) values.
So your code above actually uses the correct structure Map where you map String to a number (Integer).
Question 1
Is the number needed, is it in the file? You can calculate it from input
Adam
Mary
Michael
we know, that Adam is on a first line...
edit 1: You can use counter which you will increment every time you enter the loop. There is nothing in Java API to do that for you...
Question 2
In your question, I'm missing information about what is not working... What is your expectation that is not true?
Question 3
What in case of duplicates?
Alfa
Bravo
Alfa
Is it ok, that on the 3rd line you remap Alfa to 3?
Question 4
What is your motivation to use Set?
As I wrote in Set contains "single" items. If your item contains several fields, you can wrap in in an Object, but I do not see the benefit...
Something like
class Item {
String line;
int lineNumber;
// TODO: 1 add constructors
// TODO: 2 add getter & setters
// TODO: 3 implement equals() and hashCode()
}
and add it to Set like this:
Set mySet = ...
mySet.add(new Item(line, counter)); // you need to add such constructor

Why functions considered as first-class citizens are so important? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
Java 8 provides a bunch of functional interfaces that we can implement using lambda expressions, which allows functions to be treated as
first-class citizen (passed as arguments, returned from a method, etc...).
Example:
Stream.of("Hello", "World").forEach(str->System.out.println(str));
Why functions considered as first-class citizens are so important? Any example to demonstrate this power?
The idea is to be able to pass behavior as a parameter. This is useful, for example, in implementing the Strategy pattern.
Streams API is a perfect example of how passing behavior as a parameter is useful:
people.stream()
.map(person::name)
.map(name->new GraveStone(name, Rock.GRANITE)
.collect(Collectors.toSet())
Also it allows programmers to think in terms of functional programming instead of object-oriented programming, which is convenient for a lot of tasks, but is quite a broad thing to cover in an answer.
I think the second part of the question has been addressed well. But I want to try to answer the first question.
By definition there is more that a first-class citizen function can do. A first-class citizen function can:
be named by variables
be passed as arguments
be returned as the result of another function
participate as a member data type in a data structure (e.g., an array or list)
These are the privileges of being "first-class."
It's a matter of expressiveness. You don't have to, but in many practical cases it will make your code more readable and concise. For instance, take your code:
public class Foo {
public static void main(String[] args) {
Stream.of("Hello", "World").forEach(str->System.out.println(str));
}
}
And compare it to the most concise Java 7 implementation I could come out with:
interface Procedure<T> {
void call(T arg);
}
class Util {
static <T> void forEach(Procedure<T> proc, T... elements) {
for (T el: elements) {
proc.call(el);
}
}
}
public class Foo {
static public void main(String[] args) {
Util.forEach(
new Procedure<String>() {
public void call(String str) { System.out.println(str); }
},
"Hello", "World"
);
}
}
The result is the same, the number of lines a bit less :) Also note that for supporting Procedure instances with different number of arguments, you would have needed an interface each or (more practical) passing all the arguments as a single Parameters object. A closures would have been made in a similar way, by adding some fields to the Procedure implementation. That's a lot of boilerplate.
In fact, things like first-class "functors" and (non-mutable) closures have been around for a long time using anonymous classes, but they required a significant implementation effort. Lambdas just make things easier to read and write (at least, in most cases).
Here's a short program the shows (arguably) the primary differentiating factor.
public static void main(String[] args) {
List<Integer> input = Arrays.asList(10, 12, 13, 15, 17, 19);
List<Integer> list = pickEvensViaLists(input);
for (int i = 0; i < 2; ++i)
System.out.println(list.get(i));
System.out.println("--------------------------------------------");
pickEvensViaStreams(input).limit(2).forEach((x) -> System.out.println(x));
}
private static List<Integer> pickEvensViaLists(List<Integer> input) {
List<Integer> list = new ArrayList<Integer>(input);
for (Iterator<Integer> iter = list.iterator(); iter.hasNext(); ) {
int curr = iter.next();
System.out.println("processing list element " + curr);
if (curr % 2 != 0)
iter.remove();
}
return list;
}
private static Stream<Integer> pickEvensViaStreams(List<Integer> input) {
Stream<Integer> inputStream = input.stream();
Stream<Integer> filtered = inputStream.filter((curr) -> {
System.out.println("processing stream element " + curr);
return curr % 2 == 0;
});
return filtered;
}
This program takes an input list and prints the first two even numbers from it. It does so twice: the first time using lists with hand-written loops, the second time using streams with lambda expressions.
There are some differences in terms of the amount of code one has to write in either approach but this is not (in my mind) the main point. The difference is in how things are evaluated:
In the list-based approach the code of pickEvensViaLists() iterates over the entire list. it will remove all odd values from the list and only then will return back to main(). The list that it returned to main() will therefore contain four values: 10, 12, 20, 30 and main() will print just the first two.
In the stream-based approach the code of pickEvensViaStreams() does not actually iterate over anything. It returns a stream who else can be computed off of the input stream but it did not yet compute any one of them. Only when main() starts iterating (via forEach()) will the elements of the returned stream be computed, one by one. As main() only cares about the first two elements only two elements of the returned stream are actually computed. In other words: with stream you get lazy evaluation: streams are iterated only much as needed.
To see that let's examine the output of this program:
--------------------------------------------
list-based filtering:
processing list element 10
processing list element 12
processing list element 13
processing list element 15
processing list element 17
processing list element 19
processing list element 20
processing list element 30
10
12
--------------------------------------------
stream-based filtering:
processing stream element 10
10
processing stream element 12
12
with lists the entire input was iterated over (hence the eight "processing list element" messages). With stream only two elements were actually extracted from the input resulting in only two "processing stream element" messages.

Remove all objects in an arraylist that exist in another arraylist

I'm trying to read in from two files and store them in two separate arraylists. The files consist of words which are either alone on a line or multiple words separated by commas.
I read each file with the following code (not complete):
ArrayList<String> temp = new ArrayList<>();
FileInputStream fis;
fis = new FileInputStream(fileName);
Scanner scan = new Scanner(fis);
while (scan.hasNextLine()) {
Scanner input = new Scanner(scan.nextLine());
input.useDelimiter(",");
while (scan.hasNext()) {
String md5 = scan.next();
temp.add(md5);
}
}
scan.close();
return temp;
I now need to read two files in and remove all words from the first file which also exist in the second file (there are some duplicate words in the files). I have tried with for-loops and other such stuff, but nothing has worked so any help would be greatly appreciated!
Bonus question: I also need to find out how many duplicates there are in the two files - I've done this by adding both arraylists to a HashSet and then subtracting the size of the set from the combined size of the two arraylists - is this a good solution, or could it be done better?
You can use the removeAll method to remove the items of one list from another list.
To obtain the duplicates you can use the retainAll method, though your approach with the set is also good (and probably more efficient)
The collection facility has a convenient method for this purpose:
list1.removeAll(list2);
First you need to override equal method in your custom class and define the matching criteria of removing list
public class CustomClass{
#Override
public boolean equals(Object obj) {
try {
CustomClass licenceDetail = (CustomClass) obj;
return name.equals(licenceDetail.getName());
}
catch (Exception e)
{
return false;
}
}
}
Second you call the removeAll() method
list1.removeAll(list2);
As others have mentioned, use the Collection.removeAll method if you wish to remove all elements that exist in one Collection from the Collection you are invoking removeall on.
As for your bonus question, I'm a huge fan of Guava's Sets class. I would suggest the use of Sets.intersection as follows:
Sets.intersection(wordSetFromFile1, wordSetFromFile2).size();
Assuming you created a Set of words from both files, you can determine how many distinct words they have in common with that one liner.

I need an elegant way to exclude specific words from processing

I am writing an algorithm to extract likely keywords from a document's text. I want to count instances of words and take the top 5 as keywords. Obviously, I want to exclude "insignificant" words lest every document appears with "the" and "and" as major keywords.
Here is the strategy I've successfully used for testing:
exclusions = new ArrayList<String>();
exclusions.add("a","and","the","or");
Now that I want to do a real-life test, my exclusion list is close to 200 words long, and I'd LOVE to be able to do something like this:
exclusions = new ArrayList<String>();
exclusions.add(each word in foo.txt);
Long term, maintaining an external list (rather than a list embedded in my code) is desirable for obvious reasons. With all the file read/write methods out there in Java, I'm fairly certain that this can be done, but my search results have come up empty...I know I've got to be searching on the wrong keywords. Anyone know an elegant way to include an external list in processing?
This does not immediately address the solution you are prescribing but might give you another avenue that might be better.
Instead of deciding in advance what is useless, you could count everything and then filter out what you deem is insignificant (from a information carrying standpoint) because of its overwhelming presence. It is similar to a low-pass filter in signal processing to eliminate noise.
So in short, count everything. Then decide that if something appears with a frequency higher than a threshold you set (you'll have to determine what that threshold is from experiment, say 5% of all words are 'the', that means it does not carry information).
If you do it this way, it'll even work for foreign languages.
Just my two cents on this.
You can use a FileReader to read the Strings out of the file and add them to an ArrayList.
private List<String> createExculsions(String file) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(file));
String word = null;
List<String> exclusions = new ArrayList<String>();
while((word = reader.readLine()) != null) {
exclusions.add(word);
}
return exclusions;
}
Then you can use List<String> exclusions = createExclusions("exclusions.txt"); to create the list.
Not sure if it is elegant but here I created a simple solution to detect the language or remove noise words from tweets some years ago:
TweetDetector.java
JTweet.java which is using the data like for english
Google Guava library contains lots of useful methods that simplify routine tasks. You can use one of them to read file contents to string and split it by space character:
String contents = Files.toString(new File("foo.txt"), Charset.defaultCharset());
List<String> exclusions = Lists.newArrayList(contents.split("\\s"));
Apache Commons IO provides similar shortcuts:
String contents = FileUtils.readFileToString(new File("foo.txt"));
...
Commons-io has utilities that support this. Include commons-io as a dependency, then issue
File myFile = ...;
List<String> exclusions = FileUtils.readLines( myFile );
as described in:
http://commons.apache.org/io/apidocs/org/apache/commons/io/FileUtils.html
This assumes that every exclusion word is on a new line.
Reading from a file is pretty simple.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashSet;
public class ExcludeExample {
public static HashSet<String> readExclusions(File file) throws IOException{
BufferedReader br = new BufferedReader(new FileReader(file));
String line = "";
HashSet<String> exclusions = new HashSet<String>();
while ((line = br.readLine()) != null) {
exclusions.add(line);
}
br.close();
return exclusions;
}
public static void main(String[] args) throws IOException{
File foo = new File("foo.txt");
HashSet<String> exclusions = readExclusions(foo);
System.out.println(exclusions.contains("the"));
System.out.println(exclusions.contains("Java"));
}
}
foo.txt
the
a
and
or
I used a HashSet instead of a ArrayList because it has faster lookup.

Categories

Resources