Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 7 years ago.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Improve this question
I am keeping Node objects in a TreeSet:
public TreeSet<Node> viewNodes = new TreeSet<Node>();
Node looks like this:
public class Node implements Comparable<Node>{
private long nodeID;
...
public long getID() {
return nodeID;
}
#Override
public int compareTo(Node n) {
System.out.println("comparing: " +this + " with " + n + " -- " + new Long(nodeID).compareTo(n.getID()));
return new Long(nodeID).compareTo(n.getID());
}
#Override
public boolean equals(Object o){
if(o instanceof Node){
System.out.println((compareTo((Node)o) == 0));
return compareTo((Node)o) == 0;
}
return false;
}
#Override
public int hashCode(){
return new Long(nodeID).hashCode();
}
}
However, when I try to remove nodes, they do not get removed, and the TreeSet thinks they are not in the set!!
Remove code:
System.out.println("removing " + node);
System.out.println("viewNodes: " + viewNodes);
System.out.println("contains node?: " + viewNodes.contains(node));
viewNodes.remove(node);
System.out.println("now viewNodes looks like: " +viewNodes);
Output:
removing 5
viewNodes: [5, 4, 3, 2, 1]
comparing: 5 with 2 -- 1
comparing: 5 with 1 -- 1
contains node?: false
comparing: 5 with 2 -- 1
comparing: 5 with 1 -- 1
now viewNodes looks like: [5, 4, 3, 2, 1]
Why is this? I've implemented Comparable, shouldn't that be it?
As Andy figured out, your problem was that you changed the ID of your elements after insertion.
When using any kind of Set, you should take care not to change the elements while they are in the Set. From the Set interface documentation:
Note: Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set.
The same thing applies to Map keys, and you will find an equivalent statement in the Map interface documentation.
In TreeSet(and the underlying TreeMap that it uses) the result from the compareTo method is used to place and then later find the elements. If the results of compareTo has changed between insertion and lookup, it will probably not work as it should.
I was changing the value of ID after inserting it into the TreeSet, just as Andy suggested. I imagine this caused the node to get sorted incorrectly.
It works now, thank you!
Related
I've forgotten basically everything from my DSA class because I'm an idiot, so I'm spending winter break refreshing myself and doing practice problems I find online. One of them is returning the middle node in a singly Linked List. If there are two middle nodes, return the second one. The posted solution is way different from my answer and I can't figure out why mine is wrong.
My implementation is basically:
public static Integer findMiddle() {
LinkedList<Integer> list = new LinkedList();
list.add(5);
list.add(7);
list.add(11);
list.add(13);
list.add(15);
list.add(17);
return list.get(list.size()/2);
}
EDIT: Here is the given online answer:
void printMiddle()
{
Node slow_ptr = head;
Node fast_ptr = head;
while (fast_ptr != null && fast_ptr.next != null) {
fast_ptr = fast_ptr.next.next;
slow_ptr = slow_ptr.next;
}
System.out.println("The middle element is ["
+ slow_ptr.data + "] \n");
}
But the online answer is a bit more complicated than that. I don't really understand why this is wrong (again, I'm an idiot). If the linked list holds Integers, I would be returning the Integer, right? What would be the benefit of returning a Node over returning the object in the list, like you would in an ArrayList?
Thank you to anyone reading this! I know this is a silly question I just don't quite understand why.
This question seems very much like what you're attempting to solve: https://leetcode.com/problems/middle-of-the-linked-list/
But short of seeing the exact question you're provided, the "book answer" you have is very likely assuming you don't have access to the whole list; rather, just the head (entry point) ListNode. Which means you're going to have to traverse it to the end, and that's where the Slow & Fast Pointer technique is useful.
If we assume the question provides access to the entire LinkedList object, then your answer is fine, since you can get its size()/2.
Please pardon my understanding towards priority Queue and Comparator in Java.
It seems ,I am able to implement basic comparator for Priority Queue based on some sort order.
But I am not able to come up with something for the below scenario :
1. Given a list of Files with name convention xx_yy_zz.dat .<br/>
2.xx,yy,zz can be from 00-50 <br/>
3.I need to process the files with xx=30 first,xx=35 second xx=40 third and then the rest.<br/>
Since I have limited knowledge with Priority Queue ,I tried to implement it which i was able to sort but only in asc or desc value of xx which was not the requirement.
My approach was
put the list of file names in priority Queue ,split the filename on regex "_"
then compare the first index of split array using comparator based on it values but as expected i failed miserably since my requirement was something different
Please share some ideas/approach.
It seems sadly ,I am not able to come up with the a required comparator for my case .
Nevertheless thanking you in anticipation
You can use simple if statements inside the compare() method to check if one string starts with "30" and the other does not. Then you know that this string must come before the other one. You run the following if statements like this on the first part of the filenames:
Are they the same?
Is the left one 30?
Is the right one 30?
Is the left one 35?
Is the right one 35?
Is the left one 40?
Is the right one 40?
The comparator might look like this:
public int compare(String a, String b) {
String[] splitA = a.split("_");
String[] splitB = b.split("_");
if (splitA[0].equals(splitB[0])) {
return 0;
}
if (splitA[0].equals("30")) {
return -1;
}
if (splitB[0].equals("30")) {
return 1;
}
if (splitA[0].equals("35")) {
return -1;
}
if (splitB[0].equals("35")) {
return 1;
}
if (splitA[0].equals("40")) {
return -1;
}
if (splitB[0].equals("40")) {
return 1;
}
return 0;
}
With the following test source code:
System.out.println(Arrays.toString(data));
Arrays.sort(data, new SpecialComparator());
System.out.println(Arrays.toString(data));
You might get an output like this (depending on the data array):
[30_45_35.dat, 00_12_34.dat, 35_50_20.dat, 40_03_05.dat, 33_28_14.dat,
30_16_31.dat, 20_29_23.dat, 24_41_29.dat, 30_49_18.dat, 40_12_13.dat]
[30_45_35.dat, 30_16_31.dat, 30_49_18.dat, 35_50_20.dat, 40_03_05.dat,
40_12_13.dat, 00_12_34.dat, 33_28_14.dat, 20_29_23.dat, 24_41_29.dat]
(new lines added for clarity)
As you see you have the 30s first, then the only 35 second, then the 40s third and after that all the remaining stuff. You might want to use compareTo() on the strings in case the compareTo method would return 0 to get better "sub sorting" of strings, which would be equal based on this basic sorting above.
May be I'm not understand what exactly you need... but simply try this code and it sort me all strings if they has two digits on the begining
public static void main(String[] args) {
PriorityQueue<String> q = new PriorityQueue<String>((first, second) -> {
return Integer.parseInt(first.substring(0, 2)) - Integer.parseInt(second.substring(0, 2));
//and if you want to reverse order, simply add "-" like this:
//return -(Integer.parseInt(first.substring(0, 2)) - Integer.parseInt(second.substring(0, 2)));
});
q.add("23lk");
q.add("22lkjl");
q.add("45ljl");
for(String str : q) {
System.out.println(str);
}
}
}
adn output
22lkjl
23lk
45ljl
If this not solution, please explain problem with more details, may be I or anybody else will help you.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
So in an attempt to keep up with the times, I would like to learn what I can about Java 8's new functional operations. Beyond the opinions of which looks nicer, which is totally opinion based, would someone like to describe in detail the positives(and possibly negatives) in using Java 8's new functional programming style to iterate arrays?
This is what I mean:
Pre-Java 8:
for(Object item: itemList){
item.doSomething();
}
Java 8:
itemList.stream().forEach((item) -> {
item.doSomething();
});
The answers have enlightened me, so I will write something to demonstrate it's potential.
static int pos = 0;
public static void main(String[] args) {
List<Worker> workers = Arrays.asList(new Worker[1000]);
workers.replaceAll(worker -> new Worker(pos++));
workers.parallelStream().forEach(Worker::startJob);
}
public static class Worker {
final int pos;
public Worker(int pos) {
this.pos = pos;
}
public synchronized void startJob() {
try {
wait(100);
} catch (InterruptedException ex) {
Logger.global.log(Level.SEVERE, null, ex);
}
System.out.println("Finished... " + pos);
}
}
Only a partial answer, but the general point of the iterators is moving from external iteration to internal iteration. The foreach just a replacement, but consider something like the following (from Java 8 Lambdas) simulating the throwing of two dice:
public Map < Integer, Double > parallelDiceRolls() {
double fraction = 1.0 / N;
return IntStream.range( 0, N) .parallel()
.mapToObj( twoDiceThrows())
.collect( groupingBy( side -> side, summingDouble( n -> fraction)));
}
This is running a parallel operation against the stream, removing all external iteration requirements and all manual threading requirements. It replaces 50-60 lines of code.
It also moves from a focus on how to accomplish something (such as the OP's pre-Java 8 example) to what to accomplish.
Consider a Artist class that has an .isFrom(String) method. In the OP's first example, to count how many are from Liverpool, the code would be something like:
int count = 0;
for (Artist artist : allArtists) {
if (artist.isFrom("Liverpool")) {
count++;
}
}
Notice that the the desire to accumulate is lost in the loop and the filtering. Contrast with:
allArtists.stream()
.filter(artist -> artist.isFrom("Liverpool")
.count();
Now the logic is clear -- a filtering and a count. The iteration is now internal rather than external.
There are many additional examples, rationales, and preferences. But I think it is more than "beauty" -- it is a focus on the what, not the how when one considers iteratation.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed last year.
Improve this question
I have an a ChoiceBox that lists months values, when the user choose a value, it execute this lambda expression:
private TableView<IncomeFX> tableIncome;
private ChoiceBox<Month> choiceBoxIncomeMonths;
private ChangeListener<Month> setChoiceBoxIncomeMonthsBehaviour(){
ChangeListener<Month> months = (ObservableValue<? extends Month> observable, Month oldValue, Month newValue) -> {
incomesData.clear();
Year selectedYear = choiceBoxIncomeYears.getSelectionModel().getSelectedItem();
ObservableList<IncomeFX> temp = incomeManager.getIncomesOf(selectedYear, newValue);
incomesData.addAll(temp);
};
return months;
}
and how i add the listener:
choiceBoxIncomeMonths.getSelectionModel().selectedItemProperty().addListener(setChoiceBoxIncomeMonthsBehaviour());
when I click on the choicebox, i get:
Exception in thread "JavaFX Application Thread" java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:386)
at java.util.AbstractList$Itr.next(AbstractList.java:355)
at java.util.AbstractCollection.addAll(AbstractCollection.java:343)
at javafx.collections.ModifiableObservableListBase.addAll(ModifiableObservableListBase.java:99)
at lite.money.ui.MainUI.lambda$1(MainUI.java:160)
at lite.money.ui.MainUI$$Lambda$120/1680764266.changed(Unknown Source)
it indicate that the problem is in the line where I call: addAll(temp)
how can i solve this ??? thanks
Since you haven't posted all the code, I'm going to guess you are running code on another thread that is trying to interact with the JavaFX data. When another thread tries to do this, it will throw an exception since only the JavaFX thread should be interacting with the data.
I can't really offer any more advice because I don't have the full codebase of what you are doing to truly say "yes at line X you are having thread Y access location X when it should not be."
Are you adding this on another thread perhaps? You will know the application better than I would since I don't have anymore code to go off of.
here is how i solve it, it's a bad code i know, but i don't know any other solution, i have to clear it twice or the items will be added like if i didn't clear it, if you do have an other solution i will be happy:
private ChangeListener<Month> setChoiceBoxIncomeMonthsBehaviour(){
ChangeListener<Month> months = (ObservableValue<? extends Month> observable, Month oldValue, Month newValue) -> {
if (!lastMonthValuesFired) {
incomesData.clear();
Year selectedYear = choiceBoxIncomeYears.getSelectionModel().getSelectedItem();
ObservableList<IncomeFX> temp = incomeManager.getIncomesOf(selectedYear, newValue);
ObservableList<IncomeFX> temp2 = FXCollections.observableList(new ArrayList<IncomeFX>());
for (IncomeFX t : temp) {
temp2.add(t);
}
incomesData.clear();
incomesData.addAll(temp2);
}
};
return months;
}
I had the same problem and did some research, this is the solution that I found that worked for me:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* Java Program to demonstrate how to deal with
* ConcurrentModificationException.
* Unlike the name suggests, this error can come even if only
* one thread is modifying the collection e.g. List.
* It happens when you modify collection
* while iterating over it e.g. adding new element or removing elements.
*
* If you want to remove elements while traversing list then
* make sure you use Iterator's remove() method or not ArrayList's remove()
* method() to avoid ConcurrentModificationExcetpion.
*
* #author WINDOWS 8
*
*/
public class ConcurrentModExceptionDemo{
public static void main(String args[]) {
List<String> listOfPhones = new ArrayList<String>(Arrays.asList(
"iPhone 6S", "iPhone 6", "iPhone 5", "Samsung Galaxy 4",
"Lumia Nokia"));
System.out.println("list of phones: " + listOfPhones);
// Iterating and removing objects from list
// This is wrong way, will throw ConcurrentModificationException
for(String phone : listOfPhones){
if(phone.startsWith("iPhone")){
// listOfPhones.remove(phone); // will throw exception
}
}
// The Right way, iterating elements using Iterator's remove() method
for(Iterator<String> itr = listOfPhones.iterator();
itr.hasNext();){
String phone = itr.next();
if(phone.startsWith("iPhone")){
// listOfPhones.remove(phone); // wrong again
itr.remove(); // right call
}
}
System.out.println("list after removal: " + listOfPhones);
}
}
Source
This question already has answers here:
How to compare two java objects [duplicate]
(5 answers)
Closed 9 years ago.
I am trying to search through a collection of an ArrayList if pairs. What I want to be able to do, is to go through the collection and find the first value in a pair and return the second value of that pair. The problem I am having is that the check I have to find the first value doesn't seem to be working, so every time I search, I end up returning null. I know that the problem exists with my if statement, but I cannot seem to sort out what it is I am doing wrong. Since this is a homework assignment, I can't show all the code to my pair class, or my pair list class, but I can show you the method I have for searching the first value:
public S findFirst(F firstValue) {
Iterator<Pair> myIter = this.iterator();
S tmp2 = null;
while (myIter.hasNext()) {
Pair tmp1 = myIter.next();
if (tmp1.getFirst() == firstCall) {
tmp2 = (S) tmp1.getSecond();
}
}
return tmp2;
}
If I throw in an else statement that just calls what I am attempting to do in my if check, like this:
else{
tmp2 = (S) tmp1.getSecond();
}
then whenever I test for the first value, I get the second value, so I know I am at least on the correct path, but I am assuming that I am doing something wrong with what I am checking for in my if statement. Does anyone know how I can correctly do this, (and please bear in mind that this is homework, so a guide to how to figure this out is far more valuable to me than just some random answer, I want to learn, not just be given an answer) Thanks in advance!
Don't use == to compare objects. Override and use equals().
I think
if (tmp1.getFirst() == firstCall)
should probably say
if (tmp1.getFirst().equals(firstValue))
The important difference is that == checks whether two expressions refer to the exact same object. You're more interested in knowing whether your two expressions actually refer to objects that are equal.
Try this:
if (tmp1.getFirst().equals(firstValue))
instead of
if (tmp1.getFirst() == firstCall)
Also you can override your own equals method.
You should never use == to compare objects.
Check How to compare two java objects
What Matt says, (don't use == ) but I think a bigger problem is that you don't return the 'first' encounter.... your if statement should look like:
public S findFirst(F firstValue) {
Iterator<Pair> myIter = this.iterator();
while (myIter.hasNext()) {
Pair tmp1 = myIter.next();
if (firstValue.equals(tmp1.getFirst())) {
return (S) tmp1.getSecond();
}
}
return null;
}